upstream
17
.github/ISSUE_TEMPLATE/bug.yml
vendored
|
@ -9,12 +9,23 @@ body:
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
- type: input
|
- type: textarea
|
||||||
id: ver
|
id: ver
|
||||||
attributes:
|
attributes:
|
||||||
label: Hyprland Version
|
label: Hyprland Version
|
||||||
description: "Paste here the output of `hyprctl version`."
|
description: "Paste here the output of `hyprctl version`. For hyprland after 0.34.0, paste `hyprctl systeminfo` instead."
|
||||||
placeholder: Hyprland, built from branch main at commit...
|
value: "<details>
|
||||||
|
<summary>System/Version info</summary>
|
||||||
|
|
||||||
|
|
||||||
|
```sh
|
||||||
|
|
||||||
|
<Paste the output of the command here>
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
</details>"
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
|
|
||||||
|
|
1
.github/actions/setup_base/action.yml
vendored
|
@ -23,6 +23,7 @@ runs:
|
||||||
glm \
|
glm \
|
||||||
glslang \
|
glslang \
|
||||||
go \
|
go \
|
||||||
|
hyprlang \
|
||||||
jq \
|
jq \
|
||||||
libc++ \
|
libc++ \
|
||||||
libdisplay-info \
|
libdisplay-info \
|
||||||
|
|
104
.github/workflows/ci.yaml
vendored
|
@ -8,29 +8,20 @@ jobs:
|
||||||
container:
|
container:
|
||||||
image: archlinux
|
image: archlinux
|
||||||
steps:
|
steps:
|
||||||
- name: Get required pacman pkgs
|
- name: Checkout repository actions
|
||||||
run: |
|
uses: actions/checkout@v4
|
||||||
sed -i 's/SigLevel = Required DatabaseOptional/SigLevel = Optional TrustAll/' /etc/pacman.conf
|
|
||||||
pacman --noconfirm --noprogressbar -Syyu
|
|
||||||
pacman --noconfirm --noprogressbar -Sy glslang libepoxy libfontenc libxcvt libxfont2 libxkbfile vulkan-headers vulkan-validation-layers xcb-util-errors xcb-util-renderutil xcb-util-wm xorg-fonts-encodings xorg-server-common xorg-setxkbmap xorg-xkbcomp xorg-xwayland git cmake go clang lld libc++ pkgconf meson ninja wayland wayland-protocols libinput libxkbcommon pixman glm libdrm libglvnd cairo pango systemd scdoc base-devel seatd python libliftoff
|
|
||||||
- name: Set up user
|
|
||||||
run: |
|
|
||||||
useradd -m githubuser
|
|
||||||
echo -e "root ALL=(ALL:ALL) ALL\ngithubuser ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers
|
|
||||||
- name: Install libdisplay-info from the AUR
|
|
||||||
run: |
|
|
||||||
su githubuser -c "cd ~ && git clone https://aur.archlinux.org/libdisplay-info.git && cd ./libdisplay-info && makepkg -si --skippgpcheck --noconfirm --noprogressbar"
|
|
||||||
- name: Fix permissions for git
|
|
||||||
run: |
|
|
||||||
git config --global --add safe.directory /__w/Hyprland/Hyprland
|
|
||||||
- name: Checkout Hyprland
|
|
||||||
uses: actions/checkout@v3
|
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
sparse-checkout: .github/actions
|
||||||
|
|
||||||
|
- name: Setup base
|
||||||
|
uses: ./.github/actions/setup_base
|
||||||
|
with:
|
||||||
|
INSTALL_XORG_PKGS: true
|
||||||
|
|
||||||
- name: Build Hyprland
|
- name: Build Hyprland
|
||||||
run: |
|
run: |
|
||||||
git submodule sync --recursive && git submodule update --init --force --recursive
|
|
||||||
make all
|
make all
|
||||||
|
|
||||||
- name: Compress and package artifacts
|
- name: Compress and package artifacts
|
||||||
run: |
|
run: |
|
||||||
mkdir x86_64-pc-linux-gnu
|
mkdir x86_64-pc-linux-gnu
|
||||||
|
@ -45,6 +36,7 @@ jobs:
|
||||||
cp -r example/ hyprland/
|
cp -r example/ hyprland/
|
||||||
cp -r assets/ hyprland/
|
cp -r assets/ hyprland/
|
||||||
tar -cvf Hyprland.tar.xz hyprland
|
tar -cvf Hyprland.tar.xz hyprland
|
||||||
|
|
||||||
- name: Release
|
- name: Release
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
|
@ -57,28 +49,19 @@ jobs:
|
||||||
container:
|
container:
|
||||||
image: archlinux
|
image: archlinux
|
||||||
steps:
|
steps:
|
||||||
- name: Download dependencies
|
- name: Checkout repository actions
|
||||||
run: |
|
uses: actions/checkout@v4
|
||||||
sed -i 's/SigLevel = Required DatabaseOptional/SigLevel = Optional TrustAll/' /etc/pacman.conf
|
|
||||||
pacman --noconfirm --noprogressbar -Syyu
|
|
||||||
pacman --noconfirm --noprogressbar -Sy glslang libepoxy libfontenc libxcvt libxfont2 libxkbfile vulkan-headers vulkan-validation-layers git go clang lld libc++ pkgconf meson ninja wayland wayland-protocols libinput libxkbcommon pixman glm libdrm libglvnd cairo pango systemd scdoc base-devel seatd cmake jq python libliftoff
|
|
||||||
- name: Set up user
|
|
||||||
run: |
|
|
||||||
useradd -m githubuser
|
|
||||||
echo -e "root ALL=(ALL:ALL) ALL\ngithubuser ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers
|
|
||||||
- name: Install libdisplay-info from the AUR
|
|
||||||
run: |
|
|
||||||
su githubuser -c "cd ~ && git clone https://aur.archlinux.org/libdisplay-info.git && cd ./libdisplay-info && makepkg -si --skippgpcheck --noconfirm --noprogressbar"
|
|
||||||
- name: Checkout Hyprland
|
|
||||||
uses: actions/checkout@v3
|
|
||||||
with:
|
with:
|
||||||
submodules: true
|
sparse-checkout: .github/actions
|
||||||
|
|
||||||
|
- name: Setup base
|
||||||
|
uses: ./.github/actions/setup_base
|
||||||
|
|
||||||
- name: Configure
|
- name: Configure
|
||||||
run: |
|
run: meson setup build -Ddefault_library=static
|
||||||
meson obj-x86_64-pc-linux-gnu \
|
|
||||||
-Ddefault_library=static
|
|
||||||
- name: Compile
|
- name: Compile
|
||||||
run: ninja -C obj-x86_64-pc-linux-gnu
|
run: ninja -C build
|
||||||
|
|
||||||
noxwayland:
|
noxwayland:
|
||||||
name: "Build Hyprland in pure Wayland (Arch)"
|
name: "Build Hyprland in pure Wayland (Arch)"
|
||||||
|
@ -86,23 +69,36 @@ jobs:
|
||||||
container:
|
container:
|
||||||
image: archlinux
|
image: archlinux
|
||||||
steps:
|
steps:
|
||||||
- name: Download dependencies
|
- name: Checkout repository actions
|
||||||
run: |
|
uses: actions/checkout@v4
|
||||||
sed -i 's/SigLevel = Required DatabaseOptional/SigLevel = Optional TrustAll/' /etc/pacman.conf
|
|
||||||
pacman --noconfirm --noprogressbar -Syyu
|
|
||||||
pacman --noconfirm --noprogressbar -Sy glslang libepoxy libfontenc libxcvt libxfont2 libxkbfile vulkan-headers vulkan-validation-layers git cmake go clang lld libc++ pkgconf meson ninja wayland wayland-protocols libinput libxkbcommon pixman glm libdrm libglvnd cairo pango systemd scdoc base-devel seatd libliftoff
|
|
||||||
- name: Set up user
|
|
||||||
run: |
|
|
||||||
useradd -m githubuser
|
|
||||||
echo -e "root ALL=(ALL:ALL) ALL\ngithubuser ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers
|
|
||||||
- name: Install libdisplay-info from the AUR
|
|
||||||
run: |
|
|
||||||
su githubuser -c "cd ~ && git clone https://aur.archlinux.org/libdisplay-info.git && cd ./libdisplay-info && makepkg -si --skippgpcheck --noconfirm --noprogressbar"
|
|
||||||
- name: Checkout Hyprland
|
|
||||||
uses: actions/checkout@v3
|
|
||||||
with:
|
with:
|
||||||
submodules: true
|
sparse-checkout: .github/actions
|
||||||
|
|
||||||
|
- name: Setup base
|
||||||
|
uses: ./.github/actions/setup_base
|
||||||
|
|
||||||
- name: Configure
|
- 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
|
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
|
- name: Compile
|
||||||
run: make release
|
run: make release
|
||||||
|
|
||||||
|
clang-format:
|
||||||
|
name: "Code Style (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: clang-format check
|
||||||
|
run: ninja -C build clang-format-check
|
||||||
|
|
2
.github/workflows/nix-build.yml
vendored
|
@ -26,4 +26,4 @@ jobs:
|
||||||
name: hyprland
|
name: hyprland
|
||||||
authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
|
authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
|
||||||
|
|
||||||
- run: nix build -L ${{ matrix.command }}
|
- run: nix build .#${{ matrix.package }} -L
|
||||||
|
|
29
.github/workflows/security-checks.yml
vendored
|
@ -24,13 +24,13 @@ jobs:
|
||||||
uses: github/codeql-action/upload-sarif@v2
|
uses: github/codeql-action/upload-sarif@v2
|
||||||
with:
|
with:
|
||||||
sarif_file: ${{github.workspace}}/flawfinder_results.sarif
|
sarif_file: ${{github.workspace}}/flawfinder_results.sarif
|
||||||
|
|
||||||
codeql:
|
codeql:
|
||||||
name: CodeQL
|
name: CodeQL
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
container:
|
container:
|
||||||
image: archlinux
|
image: archlinux
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
actions: read
|
actions: read
|
||||||
contents: read
|
contents: read
|
||||||
|
@ -42,34 +42,25 @@ jobs:
|
||||||
language: [ 'cpp' ]
|
language: [ 'cpp' ]
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository actions
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
sparse-checkout: .github/actions
|
||||||
|
|
||||||
- name: Initialize CodeQL
|
- name: Initialize CodeQL
|
||||||
uses: github/codeql-action/init@v2
|
uses: github/codeql-action/init@v2
|
||||||
with:
|
with:
|
||||||
languages: ${{ matrix.language }}
|
languages: ${{ matrix.language }}
|
||||||
|
|
||||||
- name: Init Hyprland build
|
- name: Setup base
|
||||||
run: |
|
uses: ./.github/actions/setup_base
|
||||||
sed -i 's/SigLevel = Required DatabaseOptional/SigLevel = Optional TrustAll/' /etc/pacman.conf
|
|
||||||
pacman --noconfirm --noprogressbar -Syyu
|
|
||||||
pacman --noconfirm --noprogressbar -Sy glslang libepoxy libfontenc libxcvt libxfont2 libxkbfile vulkan-headers vulkan-validation-layers xcb-util-errors xcb-util-renderutil xcb-util-wm xorg-fonts-encodings xorg-server-common xorg-setxkbmap xorg-xkbcomp xorg-xwayland git cmake go clang lld libc++ pkgconf meson ninja wayland wayland-protocols libinput libxkbcommon pixman glm libdrm libglvnd cairo pango systemd scdoc base-devel seatd python libliftoff
|
|
||||||
useradd -m githubuser
|
|
||||||
echo -e "root ALL=(ALL:ALL) ALL\ngithubuser ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers
|
|
||||||
su githubuser -c "cd ~ && git clone https://aur.archlinux.org/libdisplay-info.git && cd ./libdisplay-info && makepkg -si --skippgpcheck --noconfirm --noprogressbar"
|
|
||||||
git config --global --add safe.directory /__w/Hyprland/Hyprland
|
|
||||||
|
|
||||||
- name: Checkout Hyprland
|
|
||||||
uses: actions/checkout@v3
|
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
INSTALL_XORG_PKGS: true
|
||||||
|
|
||||||
- name: Build Hyprland
|
- name: Build Hyprland
|
||||||
run: |
|
run: |
|
||||||
git submodule sync --recursive && git submodule update --init --force --recursive
|
|
||||||
make all
|
make all
|
||||||
|
|
||||||
- name: Perform CodeQL Analysis
|
- name: Perform CodeQL Analysis
|
||||||
uses: github/codeql-action/analyze@v2
|
uses: github/codeql-action/analyze@v2
|
||||||
with:
|
with:
|
||||||
|
|
28
.github/workflows/stale.yml
vendored
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
# This workflow warns and then closes issues and PRs that have had no activity for a specified amount of time.
|
||||||
|
#
|
||||||
|
# You can adjust the behavior by modifying this file.
|
||||||
|
# For more information, see:
|
||||||
|
# https://github.com/actions/stale
|
||||||
|
name: Mark stale issues and pull requests
|
||||||
|
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: '7 */4 * * *'
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
stale:
|
||||||
|
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
issues: write
|
||||||
|
pull-requests: write
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/stale@v5
|
||||||
|
with:
|
||||||
|
repo-token: ${{ secrets.STALEBOT_PAT }}
|
||||||
|
stale-issue-label: 'stale'
|
||||||
|
stale-pr-label: 'stale'
|
||||||
|
operations-per-run: 40
|
||||||
|
days-before-close: -1
|
2
.gitignore
vendored
|
@ -31,3 +31,5 @@ gmon.out
|
||||||
PKGBUILD
|
PKGBUILD
|
||||||
|
|
||||||
src/version.h
|
src/version.h
|
||||||
|
|
||||||
|
.direnv
|
||||||
|
|
3
.gitmodules
vendored
|
@ -1,7 +1,6 @@
|
||||||
[submodule "wlroots"]
|
[submodule "wlroots"]
|
||||||
path = subprojects/wlroots
|
path = subprojects/wlroots
|
||||||
url = https://github.com/DRAGONTOS/wlroots.git
|
url = https://gitlab.freedesktop.org/wlroots/wlroots.git
|
||||||
branch = 0.18.0-dev
|
|
||||||
[submodule "subprojects/hyprland-protocols"]
|
[submodule "subprojects/hyprland-protocols"]
|
||||||
path = subprojects/hyprland-protocols
|
path = subprojects/hyprland-protocols
|
||||||
url = https://github.com/hyprwm/hyprland-protocols
|
url = https://github.com/hyprwm/hyprland-protocols
|
||||||
|
|
|
@ -57,8 +57,8 @@ ExternalProject_Add(
|
||||||
wlroots
|
wlroots
|
||||||
PREFIX ${CMAKE_SOURCE_DIR}/subprojects/wlroots
|
PREFIX ${CMAKE_SOURCE_DIR}/subprojects/wlroots
|
||||||
SOURCE_DIR ${CMAKE_SOURCE_DIR}/subprojects/wlroots
|
SOURCE_DIR ${CMAKE_SOURCE_DIR}/subprojects/wlroots
|
||||||
PATCH_COMMAND sed -E -i -e "s/(soversion = 13)([^032]|$$)/soversion = 13032/g" meson.build
|
PATCH_COMMAND sed -E -i -e "s/(soversion = .*$)/soversion = 13032/g" meson.build
|
||||||
CONFIGURE_COMMAND meson setup build --buildtype=${BUILDTYPE_LOWER} -Dwerror=false -Dexamples=false -Drenderers=gles2 $<IF:$<BOOL:${WITH_ASAN}>,-Db_sanitize=address,-Db_sanitize=none> && meson setup build --buildtype=${BUILDTYPE_LOWER} -Dwerror=false -Dexamples=false -Drenderers=gles2 $<IF:$<BOOL:${WITH_ASAN}>,-Db_sanitize=address,-Db_sanitize=none> --reconfigure
|
CONFIGURE_COMMAND meson setup --reconfigure build --buildtype=${BUILDTYPE_LOWER} -Dwerror=false -Dxwayland=$<IF:$<BOOL:${NO_XWAYLAND}>,disabled,enabled> -Dexamples=false -Drenderers=gles2 $<IF:$<BOOL:${WITH_ASAN}>,-Db_sanitize=address,-Db_sanitize=none>
|
||||||
BUILD_COMMAND ninja -C build
|
BUILD_COMMAND ninja -C build
|
||||||
BUILD_ALWAYS true
|
BUILD_ALWAYS true
|
||||||
BUILD_IN_SOURCE true
|
BUILD_IN_SOURCE true
|
||||||
|
@ -101,7 +101,7 @@ message(STATUS "Checking deps...")
|
||||||
find_package(Threads REQUIRED)
|
find_package(Threads REQUIRED)
|
||||||
find_package(PkgConfig REQUIRED)
|
find_package(PkgConfig REQUIRED)
|
||||||
find_package(OpenGL REQUIRED)
|
find_package(OpenGL REQUIRED)
|
||||||
pkg_check_modules(deps REQUIRED IMPORTED_TARGET wayland-server wayland-client wayland-cursor wayland-protocols cairo libdrm xkbcommon libinput pango pangocairo pixman-1) # we do not check for wlroots, as we provide it ourselves
|
pkg_check_modules(deps REQUIRED IMPORTED_TARGET wayland-server wayland-client wayland-cursor wayland-protocols cairo libdrm xkbcommon libinput pango pangocairo pixman-1 hyprlang>=0.3.2) # we do not check for wlroots, as we provide it ourselves
|
||||||
|
|
||||||
file(GLOB_RECURSE SRCFILES CONFIGURE_DEPENDS "src/*.cpp")
|
file(GLOB_RECURSE SRCFILES CONFIGURE_DEPENDS "src/*.cpp")
|
||||||
|
|
||||||
|
|
33
Makefile
|
@ -1,22 +1,22 @@
|
||||||
PREFIX = /usr/local
|
PREFIX = /usr/local
|
||||||
|
|
||||||
legacyrenderer:
|
legacyrenderer:
|
||||||
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DLEGACY_RENDERER:BOOL=true -S . -B ./build -G Ninja
|
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -DLEGACY_RENDERER:BOOL=true -S . -B ./build -G Ninja
|
||||||
cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
|
cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
|
||||||
chmod -R 777 ./build
|
chmod -R 777 ./build
|
||||||
|
|
||||||
legacyrendererdebug:
|
legacyrendererdebug:
|
||||||
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Debug -DLEGACY_RENDERER:BOOL=true -S . -B ./build -G Ninja
|
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Debug -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -DLEGACY_RENDERER:BOOL=true -S . -B ./build -G Ninja
|
||||||
cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
|
cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
|
||||||
chmod -R 777 ./build
|
chmod -R 777 ./build
|
||||||
|
|
||||||
release:
|
release:
|
||||||
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -S . -B ./build -G Ninja
|
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -S . -B ./build -G Ninja
|
||||||
cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
|
cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
|
||||||
chmod -R 777 ./build
|
chmod -R 777 ./build
|
||||||
|
|
||||||
debug:
|
debug:
|
||||||
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Debug -S . -B ./build -G Ninja
|
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Debug -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -S . -B ./build -G Ninja
|
||||||
cmake --build ./build --config Debug --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
|
cmake --build ./build --config Debug --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
|
||||||
chmod -R 777 ./build
|
chmod -R 777 ./build
|
||||||
|
|
||||||
|
@ -42,10 +42,10 @@ install:
|
||||||
chmod 755 ${PREFIX}/bin/Hyprland
|
chmod 755 ${PREFIX}/bin/Hyprland
|
||||||
chmod 755 ${PREFIX}/bin/hyprctl
|
chmod 755 ${PREFIX}/bin/hyprctl
|
||||||
chmod 755 ${PREFIX}/bin/hyprpm
|
chmod 755 ${PREFIX}/bin/hyprpm
|
||||||
ln -s -r -f ${PREFIX}/bin/Hyprland ${PREFIX}/bin/hyprland
|
cd ${PREFIX}/bin && ln -sf Hyprland hyprland
|
||||||
if [ ! -f ${PREFIX}/share/wayland-sessions/hyprland.desktop ]; then cp ./example/hyprland.desktop ${PREFIX}/share/wayland-sessions; fi
|
if [ ! -f ${PREFIX}/share/wayland-sessions/hyprland.desktop ]; then cp ./example/hyprland.desktop ${PREFIX}/share/wayland-sessions; fi
|
||||||
mkdir -p ${PREFIX}/share/hyprland
|
mkdir -p ${PREFIX}/share/hyprland
|
||||||
cp ./assets/wall_* ${PREFIX}/share/hyprland
|
cp ./assets/wall* ${PREFIX}/share/hyprland
|
||||||
mkdir -p ${PREFIX}/share/xdg-desktop-portal
|
mkdir -p ${PREFIX}/share/xdg-desktop-portal
|
||||||
cp ./assets/hyprland-portals.conf ${PREFIX}/share/xdg-desktop-portal
|
cp ./assets/hyprland-portals.conf ${PREFIX}/share/xdg-desktop-portal
|
||||||
|
|
||||||
|
@ -106,3 +106,24 @@ man:
|
||||||
--variable=section:1 \
|
--variable=section:1 \
|
||||||
--from rst \
|
--from rst \
|
||||||
--to man > ./docs/hyprctl.1
|
--to man > ./docs/hyprctl.1
|
||||||
|
|
||||||
|
asan:
|
||||||
|
@echo -en "!!WARNING!!\nOnly run this in the TTY.\n"
|
||||||
|
@pidof Hyprland > /dev/null && echo -ne "Refusing to run with Hyprland running.\n" || echo ""
|
||||||
|
@pidof Hyprland > /dev/null && exit 1 || echo ""
|
||||||
|
|
||||||
|
rm -rf ./wayland
|
||||||
|
git reset --hard
|
||||||
|
|
||||||
|
git clone --recursive https://gitlab.freedesktop.org/wayland/wayland
|
||||||
|
cd wayland && patch -p1 < ../scripts/waylandStatic.diff && meson setup build --buildtype=debug -Db_sanitize=address -Ddocumentation=false && ninja -C build && cd ..
|
||||||
|
cp ./wayland/build/src/libwayland-server.a .
|
||||||
|
@echo "Wayland done"
|
||||||
|
|
||||||
|
patch -p1 < ./scripts/hyprlandStaticAsan.diff
|
||||||
|
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Debug -DWITH_ASAN:STRING=True -DUSE_TRACY:STRING=False -DUSE_TRACY_GPU:STRING=False -S . -B ./build -G Ninja
|
||||||
|
cmake --build ./build --config Debug --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
|
||||||
|
@echo "Hyprland done"
|
||||||
|
|
||||||
|
ASAN_OPTIONS="detect_odr_violation=0,log_path=asan.log" HYPRLAND_NO_CRASHREPORTER=1 ./build/Hyprland -c ~/.config/hypr/hyprland.conf
|
||||||
|
|
||||||
|
|
|
@ -41,6 +41,7 @@ easy IPC, much more QoL stuff than other wlr-based compositors and more...
|
||||||
- Much more QoL stuff than other wlr-based compositors
|
- Much more QoL stuff than other wlr-based compositors
|
||||||
- Custom bezier curves for the best animations
|
- Custom bezier curves for the best animations
|
||||||
- Powerful plugin support
|
- Powerful plugin support
|
||||||
|
- Built-in plugin manager
|
||||||
- Tearing support for better gaming performance
|
- Tearing support for better gaming performance
|
||||||
- Easily expandable and readable codebase
|
- Easily expandable and readable codebase
|
||||||
- Fast and active development
|
- Fast and active development
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
wallpaper_types = ['', 'anime_', 'anime2_']
|
wallpapers = ['0', '1', '2']
|
||||||
|
|
||||||
foreach type : wallpaper_types
|
foreach type : wallpapers
|
||||||
foreach size : [2, 4, 8]
|
install_data(f'wall@type@.png', install_dir: join_paths(get_option('datadir'), 'hyprland'), install_tag: 'runtime')
|
||||||
install_data(f'wall_@type@@size@K.png', install_dir: join_paths(get_option('datadir'), 'hyprland'), install_tag: 'runtime')
|
|
||||||
endforeach
|
|
||||||
endforeach
|
endforeach
|
||||||
|
|
||||||
install_data('hyprland-portals.conf', install_dir: join_paths(get_option('datadir'), 'xdg-desktop-portal'), install_tag: 'runtime')
|
install_data('hyprland-portals.conf', install_dir: join_paths(get_option('datadir'), 'xdg-desktop-portal'), install_tag: 'runtime')
|
||||||
|
|
BIN
assets/wall0.png
Normal file
After Width: | Height: | Size: 14 MiB |
BIN
assets/wall1.png
Normal file
After Width: | Height: | Size: 5.9 MiB |
BIN
assets/wall2.png
Normal file
After Width: | Height: | Size: 27 MiB |
Before Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 48 KiB |
Before Width: | Height: | Size: 146 KiB |
Before Width: | Height: | Size: 511 KiB |
Before Width: | Height: | Size: 1.3 MiB |
Before Width: | Height: | Size: 1.3 MiB |
Before Width: | Height: | Size: 502 KiB |
Before Width: | Height: | Size: 1.4 MiB |
Before Width: | Height: | Size: 1.6 MiB |
|
@ -47,7 +47,7 @@ basically, directories in /tmp/hypr are your sessions.
|
||||||
|
|
||||||
## Obtaining the Hyprland Crash Report (v0.22.0beta and up)
|
## Obtaining the Hyprland Crash Report (v0.22.0beta and up)
|
||||||
|
|
||||||
If you have `$XDG_CACHE_HOME` set, the crash report directory is `$XDG_CACHE_HOME/hyprland`. If not, it's `~/.hyprland`
|
If you have `$XDG_CACHE_HOME` set, the crash report directory is `$XDG_CACHE_HOME/hyprland`. If not, it's `$HOME/.cache/hyprland`.
|
||||||
|
|
||||||
Go to the crash report directory and you should find a file named `hyprlandCrashReport[XXXX].txt` where `[XXXX]` is the PID of the process that crashed.
|
Go to the crash report directory and you should find a file named `hyprlandCrashReport[XXXX].txt` where `[XXXX]` is the PID of the process that crashed.
|
||||||
|
|
||||||
|
|
|
@ -1,112 +1,32 @@
|
||||||
|
# This is an example Hyprland config file.
|
||||||
|
#
|
||||||
|
# Refer to the wiki for more information.
|
||||||
|
|
||||||
|
#
|
||||||
|
# Please note not all available settings / options are set here.
|
||||||
|
# For a full list, see the wiki
|
||||||
|
#
|
||||||
|
|
||||||
|
# See https://wiki.hyprland.org/Configuring/Monitors/
|
||||||
|
monitor=,preferred,auto,auto
|
||||||
|
|
||||||
|
|
||||||
# See https://wiki.hyprland.org/Configuring/Keywords/ for more
|
# See https://wiki.hyprland.org/Configuring/Keywords/ for more
|
||||||
|
|
||||||
|
# Execute your favorite apps at launch
|
||||||
# exec-once = waybar & hyprpaper & firefox
|
# exec-once = waybar & hyprpaper & firefox
|
||||||
|
|
||||||
# Source a file (multi-file configs)
|
# Source a file (multi-file configs)
|
||||||
# source = ~/.config/hypr/myColors.conf
|
# source = ~/.config/hypr/myColors.conf
|
||||||
|
|
||||||
# Startup
|
# Set programs that you use
|
||||||
#exec-once = waybar & hyprpaper & dunst
|
$terminal = kitty
|
||||||
exec-once = /usr/libexec/polkit-gnome-authentication-agent-1
|
$fileManager = dolphin
|
||||||
exec-once = hyprpm reload -n
|
$menu = wofi --show drun
|
||||||
#exec-once = wl-clip-persist --clipboard both
|
|
||||||
#exec-once = wl-paste -p -t text --watch clipman store -P --histpath="~/.local/share/clipman-primary.json"
|
|
||||||
|
|
||||||
# Plugins
|
# Some default env vars.
|
||||||
#plugin {
|
env = XCURSOR_SIZE,24
|
||||||
# split-monitor-workspaces {
|
env = QT_QPA_PLATFORMTHEME,qt5ct # change to qt6ct if you have that
|
||||||
# count = 10
|
|
||||||
# }
|
|
||||||
# hy3 {
|
|
||||||
# # disable gaps when only one window is onscreen
|
|
||||||
# no_gaps_when_only = false # default: false
|
|
||||||
#
|
|
||||||
# # policy controlling what happens when a node is removed from a group,
|
|
||||||
# # leaving only a group
|
|
||||||
# # 0 = remove the nested group
|
|
||||||
# # 1 = keep the nested group
|
|
||||||
# # 2 = keep the nested group only if its parent is a tab group
|
|
||||||
# node_collapse_policy = 2 # default: 2
|
|
||||||
#
|
|
||||||
# # special workspace
|
|
||||||
# special_scale_factor = 0.95
|
|
||||||
#
|
|
||||||
# # offset from group split direction when only one window is in a group
|
|
||||||
# group_inset = 10 # default: 10
|
|
||||||
#
|
|
||||||
# # tab group settings
|
|
||||||
# tabs {
|
|
||||||
# # height of the tab bar
|
|
||||||
# height = 15 # default: 15
|
|
||||||
#
|
|
||||||
# # padding between the tab bar and its focused node
|
|
||||||
# padding = 5 # default: 5
|
|
||||||
#
|
|
||||||
# # the tab bar should animate in/out from the top instead of below the window
|
|
||||||
# from_top = false # default: false
|
|
||||||
#
|
|
||||||
# # rounding of tab bar corners
|
|
||||||
# rounding = 5 # default: 3
|
|
||||||
#
|
|
||||||
# # render the window title on the bar
|
|
||||||
# render_text = true # default: true
|
|
||||||
#
|
|
||||||
# # font to render the window title with
|
|
||||||
# text_font = Jetbrains Mono # default: Sans
|
|
||||||
#
|
|
||||||
# # height of the window title
|
|
||||||
# text_height = 8 # default: 8
|
|
||||||
#
|
|
||||||
# # left padding of the window title
|
|
||||||
# text_padding = 3 # default: 3
|
|
||||||
#
|
|
||||||
# # active tab bar segment color
|
|
||||||
# col.active = 0xFF8330DB # default: 0xff32b4ff
|
|
||||||
#
|
|
||||||
# # urgent tab bar segment color
|
|
||||||
# col.urgent = 0xffff4f4f # default: 0xffff4f4f
|
|
||||||
#
|
|
||||||
# # inactive tab bar segment color
|
|
||||||
# col.inactive = 0xFF4D4D4D # default: 0x80808080
|
|
||||||
#
|
|
||||||
# # active tab bar text color
|
|
||||||
# col.text.active = 0xffffffff # default: 0xff000000
|
|
||||||
#
|
|
||||||
# # urgent tab bar text color
|
|
||||||
# col.text.urgent = 0xffffffff # default: 0xff000000
|
|
||||||
#
|
|
||||||
# # inactive tab bar text color
|
|
||||||
# col.text.inactive = 0xffffffff # default: 0xff000000
|
|
||||||
# }
|
|
||||||
#
|
|
||||||
# # autotiling settings
|
|
||||||
# autotile {
|
|
||||||
# # enable autotile
|
|
||||||
# enable = false # default: false
|
|
||||||
#
|
|
||||||
# # make autotile-created groups ephemeral
|
|
||||||
# ephemeral_groups = true # default: true
|
|
||||||
#
|
|
||||||
# # if a window would be squished smaller than this width, a vertical split will be created
|
|
||||||
# # -1 = never automatically split vertically
|
|
||||||
# # 0 = always automatically split vertically
|
|
||||||
# # <number> = pixel height to split at
|
|
||||||
# trigger_width = 0 # default: 0
|
|
||||||
#
|
|
||||||
# # if a window would be squished smaller than this height, a horizontal split will be created
|
|
||||||
# # -1 = never automatically split horizontally
|
|
||||||
# # 0 = always automatically split horizontally
|
|
||||||
# # <number> = pixel height to split at
|
|
||||||
# trigger_height = 0 # default: 0
|
|
||||||
#
|
|
||||||
# # a space or comma separated list of workspace ids where autotile should be enabled
|
|
||||||
# # it's possible to create an exception rule by prefixing the definition with "not:"
|
|
||||||
# # workspaces = 1,2 # autotiling will only be enabled on workspaces 1 and 2
|
|
||||||
# # workspaces = not:1,2 # autotiling will be enabled on all workspaces except 1 and 2
|
|
||||||
# workspaces = all # default: all
|
|
||||||
# }
|
|
||||||
# }
|
|
||||||
#}
|
|
||||||
|
|
||||||
# For all categories, see https://wiki.hyprland.org/Configuring/Variables/
|
# For all categories, see https://wiki.hyprland.org/Configuring/Variables/
|
||||||
input {
|
input {
|
||||||
|
@ -119,7 +39,7 @@ input {
|
||||||
follow_mouse = 1
|
follow_mouse = 1
|
||||||
|
|
||||||
touchpad {
|
touchpad {
|
||||||
natural_scroll = no
|
natural_scroll = false
|
||||||
}
|
}
|
||||||
|
|
||||||
sensitivity = 0 # -1.0 - 1.0, 0 means no modification.
|
sensitivity = 0 # -1.0 - 1.0, 0 means no modification.
|
||||||
|
@ -130,32 +50,37 @@ general {
|
||||||
|
|
||||||
gaps_in = 5
|
gaps_in = 5
|
||||||
gaps_out = 20
|
gaps_out = 20
|
||||||
border_size = 3
|
border_size = 2
|
||||||
col.active_border = 0xFF8330DB 0xFF3e136c
|
col.active_border = rgba(33ccffee) rgba(00ff99ee) 45deg
|
||||||
col.inactive_border = 0xFF4D4D4D 0xFF333333
|
col.inactive_border = rgba(595959aa)
|
||||||
|
|
||||||
layout = dwindle
|
layout = dwindle
|
||||||
|
|
||||||
|
# Please see https://wiki.hyprland.org/Configuring/Tearing/ before you turn this on
|
||||||
|
allow_tearing = false
|
||||||
}
|
}
|
||||||
|
|
||||||
decoration {
|
decoration {
|
||||||
# See https://wiki.hyprland.org/Configuring/Variables/ for more
|
# See https://wiki.hyprland.org/Configuring/Variables/ for more
|
||||||
|
|
||||||
rounding = 10
|
rounding = 10
|
||||||
|
|
||||||
blur {
|
blur {
|
||||||
enabled = true
|
enabled = true
|
||||||
size = 1.5
|
size = 3
|
||||||
passes = 1
|
passes = 1
|
||||||
|
|
||||||
|
vibrancy = 0.1696
|
||||||
}
|
}
|
||||||
|
|
||||||
drop_shadow = yes
|
drop_shadow = true
|
||||||
shadow_range = 4
|
shadow_range = 4
|
||||||
shadow_render_power = 3
|
shadow_render_power = 3
|
||||||
col.shadow = rgba(1a1a1aee)
|
col.shadow = rgba(1a1a1aee)
|
||||||
}
|
}
|
||||||
|
|
||||||
animations {
|
animations {
|
||||||
enabled = yes
|
enabled = true
|
||||||
|
|
||||||
# Some default animations, see https://wiki.hyprland.org/Configuring/Animations/ for more
|
# Some default animations, see https://wiki.hyprland.org/Configuring/Animations/ for more
|
||||||
|
|
||||||
|
@ -164,14 +89,15 @@ animations {
|
||||||
animation = windows, 1, 7, myBezier
|
animation = windows, 1, 7, myBezier
|
||||||
animation = windowsOut, 1, 7, default, popin 80%
|
animation = windowsOut, 1, 7, default, popin 80%
|
||||||
animation = border, 1, 10, default
|
animation = border, 1, 10, default
|
||||||
|
animation = borderangle, 1, 8, default
|
||||||
animation = fade, 1, 7, default
|
animation = fade, 1, 7, default
|
||||||
animation = workspaces, 1, 4, default
|
animation = workspaces, 1, 6, default
|
||||||
}
|
}
|
||||||
|
|
||||||
dwindle {
|
dwindle {
|
||||||
# See https://wiki.hyprland.org/Configuring/Dwindle-Layout/ for more
|
# See https://wiki.hyprland.org/Configuring/Dwindle-Layout/ for more
|
||||||
pseudotile = yes # master switch for pseudotiling. Enabling is bound to mainMod + P in the keybinds section below
|
pseudotile = true # master switch for pseudotiling. Enabling is bound to mainMod + P in the keybinds section below
|
||||||
preserve_split = yes # you probably want this
|
preserve_split = true # you probably want this
|
||||||
}
|
}
|
||||||
|
|
||||||
master {
|
master {
|
||||||
|
@ -181,39 +107,41 @@ master {
|
||||||
|
|
||||||
gestures {
|
gestures {
|
||||||
# See https://wiki.hyprland.org/Configuring/Variables/ for more
|
# See https://wiki.hyprland.org/Configuring/Variables/ for more
|
||||||
workspace_swipe = off
|
workspace_swipe = false
|
||||||
}
|
}
|
||||||
|
|
||||||
# unscale XWayland
|
misc {
|
||||||
xwayland {
|
# See https://wiki.hyprland.org/Configuring/Variables/ for more
|
||||||
force_zero_scaling = true
|
force_default_wallpaper = -1 # Set to 0 or 1 to disable the anime mascot wallpapers
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Example per-device config
|
||||||
|
# See https://wiki.hyprland.org/Configuring/Keywords/#per-device-input-configs for more
|
||||||
|
device {
|
||||||
|
name = epic-mouse-v1
|
||||||
|
sensitivity = -0.5
|
||||||
|
}
|
||||||
|
|
||||||
|
# Example windowrule v1
|
||||||
|
# windowrule = float, ^(kitty)$
|
||||||
|
# Example windowrule v2
|
||||||
|
# windowrulev2 = float,class:^(kitty)$,title:^(kitty)$
|
||||||
# See https://wiki.hyprland.org/Configuring/Window-Rules/ for more
|
# See https://wiki.hyprland.org/Configuring/Window-Rules/ for more
|
||||||
windowrule = rounding 1,class:^(Wine)$
|
windowrulev2 = suppressevent maximize, class:.* # You'll probably like this.
|
||||||
windowrulev2 = opacity 0.8 0.8,class:^(kitty)$
|
|
||||||
windowrulev2=float,class:^(hyprland.share.picker)$
|
|
||||||
windowrule = float,^(Steamwebhelper)$
|
|
||||||
windowrule = float, title:^(Steamwebhelper)$
|
|
||||||
windowrule = float, title:^(pop-up)
|
|
||||||
windowrule = float, class:^(xdg-desktop-portal-kde)
|
|
||||||
windowrule = float, class:^(Wine)
|
|
||||||
# See https://wiki.hyprland.org/Configuring/Keywords/ for more
|
# See https://wiki.hyprland.org/Configuring/Keywords/ for more
|
||||||
$mainMod = SUPER
|
$mainMod = SUPER
|
||||||
|
|
||||||
# Example binds, see https://wiki.hyprland.org/Configuring/Binds/ for more
|
# Example binds, see https://wiki.hyprland.org/Configuring/Binds/ for more
|
||||||
bind = $mainMod, RETURN, exec, $terminal
|
bind = $mainMod, Q, exec, $terminal
|
||||||
bind = $mainMod, Q, killactive,
|
bind = $mainMod, C, killactive,
|
||||||
bind = $mainMod SHIFT, Q, exit,
|
bind = $mainMod, M, exit,
|
||||||
bind = $mainMod, F, fullscreen,
|
bind = $mainMod, E, exec, $fileManager
|
||||||
bind = $mainMod, SPACE, togglefloating,
|
bind = $mainMod, V, togglefloating,
|
||||||
bind = $mainMod, L, exec, gtklock
|
bind = $mainMod, R, exec, $menu
|
||||||
bind = $mainMod CTRL, B, exec, killall waybar && waybar -c /home/$USER/.config/waybar/config-hypr
|
|
||||||
|
|
||||||
bind = $mainMod, D, exec, rofi -show run
|
|
||||||
bind = $mainMod, P, pseudo, # dwindle
|
bind = $mainMod, P, pseudo, # dwindle
|
||||||
bind = $mainMod, J, togglesplit, # dwindle
|
bind = $mainMod, J, togglesplit, # dwindle
|
||||||
bind = $mainMod, Print, exec, grim -g "$(slurp)" - | swappy -f - # take a screenshot
|
|
||||||
|
|
||||||
# Move focus with mainMod + arrow keys
|
# Move focus with mainMod + arrow keys
|
||||||
bind = $mainMod, left, movefocus, l
|
bind = $mainMod, left, movefocus, l
|
||||||
|
@ -221,12 +149,6 @@ bind = $mainMod, right, movefocus, r
|
||||||
bind = $mainMod, up, movefocus, u
|
bind = $mainMod, up, movefocus, u
|
||||||
bind = $mainMod, down, movefocus, d
|
bind = $mainMod, down, movefocus, d
|
||||||
|
|
||||||
# Move focused with mainMod + arrow keys
|
|
||||||
bind = $mainMod SHIFT, left, movewindow, l
|
|
||||||
bind = $mainMod SHIFT, right, movewindow, r
|
|
||||||
bind = $mainMod SHIFT, up, movewindow, u
|
|
||||||
bind = $mainMod SHIFT, down, movewindow, d
|
|
||||||
|
|
||||||
# Switch workspaces with mainMod + [0-9]
|
# Switch workspaces with mainMod + [0-9]
|
||||||
bind = $mainMod, 1, workspace, 1
|
bind = $mainMod, 1, workspace, 1
|
||||||
bind = $mainMod, 2, workspace, 2
|
bind = $mainMod, 2, workspace, 2
|
||||||
|
@ -251,22 +173,9 @@ bind = $mainMod SHIFT, 8, movetoworkspace, 8
|
||||||
bind = $mainMod SHIFT, 9, movetoworkspace, 9
|
bind = $mainMod SHIFT, 9, movetoworkspace, 9
|
||||||
bind = $mainMod SHIFT, 0, movetoworkspace, 10
|
bind = $mainMod SHIFT, 0, movetoworkspace, 10
|
||||||
|
|
||||||
|
# Example special workspace (scratchpad)
|
||||||
# vm fix
|
bind = $mainMod, S, togglespecialworkspace, magic
|
||||||
bind=CTRL,ALT_L,submap,passthrough
|
bind = $mainMod SHIFT, S, movetoworkspace, special:magic
|
||||||
submap=passthrough
|
|
||||||
bindr=CTRL,Escape,submap,reset
|
|
||||||
submap=reset
|
|
||||||
|
|
||||||
# Repeat this for each scratchpad you need
|
|
||||||
# BROWSER
|
|
||||||
animation=specialWorkspace,0,0,default
|
|
||||||
|
|
||||||
# kitty
|
|
||||||
#bind = $mainMod, y, togglespecialworkspace, kitty
|
|
||||||
#bind = $mainMod SHIFT, y, movetoworkspace, special:kitty
|
|
||||||
|
|
||||||
bind = $mainMod, x, exec, hyprctl dispatch togglespecialworkspace && hyprctl dispatch togglespecialworkspace
|
|
||||||
|
|
||||||
# Scroll through existing workspaces with mainMod + scroll
|
# Scroll through existing workspaces with mainMod + scroll
|
||||||
bind = $mainMod, mouse_down, workspace, e+1
|
bind = $mainMod, mouse_down, workspace, e+1
|
||||||
|
|
47
flake.lock
generated
|
@ -23,13 +23,36 @@
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"hyprlang": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs": [
|
||||||
|
"nixpkgs"
|
||||||
|
],
|
||||||
|
"systems": [
|
||||||
|
"systems"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1708787654,
|
||||||
|
"narHash": "sha256-7ACgM3ZuAhPqurXHUvR2nWMRcnmzGGPjLK6q4DSTelI=",
|
||||||
|
"owner": "hyprwm",
|
||||||
|
"repo": "hyprlang",
|
||||||
|
"rev": "0fce791ba2334aca183f2ed42399518947550d0d",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "hyprwm",
|
||||||
|
"repo": "hyprlang",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1703438236,
|
"lastModified": 1708807242,
|
||||||
"narHash": "sha256-aqVBq1u09yFhL7bj1/xyUeJjzr92fXVvQSSEx6AdB1M=",
|
"narHash": "sha256-sRTRkhMD4delO/hPxxi+XwLqPn8BuUq6nnj4JqLwOu0=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "5f64a12a728902226210bf01d25ec6cbb9d9265b",
|
"rev": "73de017ef2d18a04ac4bfd0c02650007ccb31c2a",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
@ -42,6 +65,7 @@
|
||||||
"root": {
|
"root": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"hyprland-protocols": "hyprland-protocols",
|
"hyprland-protocols": "hyprland-protocols",
|
||||||
|
"hyprlang": "hyprlang",
|
||||||
"nixpkgs": "nixpkgs",
|
"nixpkgs": "nixpkgs",
|
||||||
"systems": "systems",
|
"systems": "systems",
|
||||||
"wlroots": "wlroots",
|
"wlroots": "wlroots",
|
||||||
|
@ -67,18 +91,18 @@
|
||||||
"flake": false,
|
"flake": false,
|
||||||
"locked": {
|
"locked": {
|
||||||
"host": "gitlab.freedesktop.org",
|
"host": "gitlab.freedesktop.org",
|
||||||
"lastModified": 1701368958,
|
"lastModified": 1708558866,
|
||||||
"narHash": "sha256-7kvyoA91etzVEl9mkA/EJfB6z/PltxX7Xc4gcr7/xlo=",
|
"narHash": "sha256-Mz6hCtommq7RQfcPnxLINigO4RYSNt23HeJHC6mVmWI=",
|
||||||
"owner": "wlroots",
|
"owner": "wlroots",
|
||||||
"repo": "wlroots",
|
"repo": "wlroots",
|
||||||
"rev": "5d639394f3e83b01596dcd166a44a9a1a2583350",
|
"rev": "0cb091f1a2d345f37d2ee445f4ffd04f7f4ec9e5",
|
||||||
"type": "gitlab"
|
"type": "gitlab"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"host": "gitlab.freedesktop.org",
|
"host": "gitlab.freedesktop.org",
|
||||||
"owner": "wlroots",
|
"owner": "wlroots",
|
||||||
"repo": "wlroots",
|
"repo": "wlroots",
|
||||||
"rev": "5d639394f3e83b01596dcd166a44a9a1a2583350",
|
"rev": "0cb091f1a2d345f37d2ee445f4ffd04f7f4ec9e5",
|
||||||
"type": "gitlab"
|
"type": "gitlab"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -87,6 +111,9 @@
|
||||||
"hyprland-protocols": [
|
"hyprland-protocols": [
|
||||||
"hyprland-protocols"
|
"hyprland-protocols"
|
||||||
],
|
],
|
||||||
|
"hyprlang": [
|
||||||
|
"hyprlang"
|
||||||
|
],
|
||||||
"nixpkgs": [
|
"nixpkgs": [
|
||||||
"nixpkgs"
|
"nixpkgs"
|
||||||
],
|
],
|
||||||
|
@ -95,11 +122,11 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1703514399,
|
"lastModified": 1708696469,
|
||||||
"narHash": "sha256-VRr5Xc4S/VPr/gU3fiOD3vSIL2+GJ+LUrmFTWTwnTz4=",
|
"narHash": "sha256-shh5wmpeYy3MmsBfkm4f76yPsBDGk6OLYRVG+ARy2F0=",
|
||||||
"owner": "hyprwm",
|
"owner": "hyprwm",
|
||||||
"repo": "xdg-desktop-portal-hyprland",
|
"repo": "xdg-desktop-portal-hyprland",
|
||||||
"rev": "0a318a7a217a6402b0b705837cd5b50b0e94b31b",
|
"rev": "1b713911c2f12b96c2574474686e4027ac4bf826",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
10
flake.nix
|
@ -12,7 +12,7 @@
|
||||||
host = "gitlab.freedesktop.org";
|
host = "gitlab.freedesktop.org";
|
||||||
owner = "wlroots";
|
owner = "wlroots";
|
||||||
repo = "wlroots";
|
repo = "wlroots";
|
||||||
rev = "5d639394f3e83b01596dcd166a44a9a1a2583350";
|
rev = "0cb091f1a2d345f37d2ee445f4ffd04f7f4ec9e5";
|
||||||
flake = false;
|
flake = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -22,11 +22,18 @@
|
||||||
inputs.systems.follows = "systems";
|
inputs.systems.follows = "systems";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
hyprlang = {
|
||||||
|
url = "github:hyprwm/hyprlang";
|
||||||
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
|
inputs.systems.follows = "systems";
|
||||||
|
};
|
||||||
|
|
||||||
xdph = {
|
xdph = {
|
||||||
url = "github:hyprwm/xdg-desktop-portal-hyprland";
|
url = "github:hyprwm/xdg-desktop-portal-hyprland";
|
||||||
inputs.nixpkgs.follows = "nixpkgs";
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
inputs.systems.follows = "systems";
|
inputs.systems.follows = "systems";
|
||||||
inputs.hyprland-protocols.follows = "hyprland-protocols";
|
inputs.hyprland-protocols.follows = "hyprland-protocols";
|
||||||
|
inputs.hyprlang.follows = "hyprlang";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -86,6 +93,7 @@
|
||||||
name = "hyprland-shell";
|
name = "hyprland-shell";
|
||||||
nativeBuildInputs = with pkgsFor.${system}; [cmake python3];
|
nativeBuildInputs = with pkgsFor.${system}; [cmake python3];
|
||||||
buildInputs = [self.packages.${system}.wlroots-hyprland];
|
buildInputs = [self.packages.${system}.wlroots-hyprland];
|
||||||
|
hardeningDisable = ["fortify"];
|
||||||
inputsFrom = [
|
inputsFrom = [
|
||||||
self.packages.${system}.wlroots-hyprland
|
self.packages.${system}.wlroots-hyprland
|
||||||
self.packages.${system}.hyprland
|
self.packages.${system}.hyprland
|
||||||
|
|
136
hyprctl/main.cpp
|
@ -23,49 +23,42 @@
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
|
||||||
const std::string USAGE = R"#(usage: hyprctl [flags] [<command> [args]]
|
const std::string USAGE = R"#(usage: hyprctl [(opt)flags] [command] [(opt)args]
|
||||||
hyprctl --batch {<command 1> [args] ; <command 2> [args] ; ...}
|
|
||||||
LISTING COMMANDS:
|
commands:
|
||||||
monitors: List outputs
|
activewindow
|
||||||
workspaces: List all workspaces
|
activeworkspace
|
||||||
activeworkspace: Get currently active workspace
|
binds
|
||||||
clients: List clients (e.g. windows)
|
clients
|
||||||
activewindow: Get currently active window
|
cursorpos
|
||||||
layers: List layers
|
decorations
|
||||||
animations: List animations and bezier curves in use
|
devices
|
||||||
devices: List devices
|
dispatch
|
||||||
binds: List registered binds
|
getoption
|
||||||
instances: List running Hyprland instances
|
globalshortcuts
|
||||||
layouts: List layouts
|
hyprpaper
|
||||||
globalshortcuts: List global shortcuts
|
instances
|
||||||
version: Print hyprland version
|
keyword
|
||||||
CONFIGURATION COMMANDS:
|
kill
|
||||||
keyword <keyword> [args]: Execute a keyword
|
layers
|
||||||
getoption <option>: Get value of <option>
|
layouts
|
||||||
reload: Reload configurations
|
monitors
|
||||||
PLUGIN:
|
notify
|
||||||
plugin list: List loaded plugins
|
plugin
|
||||||
plugin load <path>: Load plugin from <path>
|
reload
|
||||||
plugin unload <path>: Unload plugin at <path>
|
setcursor
|
||||||
THEMING:
|
seterror
|
||||||
hyprpaper <keywords> Issue hyprpaper keywords using IPC
|
setprop
|
||||||
splash: Prints the current random splash
|
splash
|
||||||
cursorpos: Get the current cursor position in global layout coordinates
|
switchxkblayout
|
||||||
setcursor <theme> <size>: Set cursor theme and size, (except for GTK)
|
systeminfo
|
||||||
ADDITIONAL COMMANDS:
|
version
|
||||||
dispatch <name> [args]: Run a dispatcher
|
workspacerules
|
||||||
kill: Enter kill mode, where you can kill an app by clicking on it,
|
workspaces
|
||||||
use ESCAPE to quit kill mode
|
|
||||||
switchxkblayout <args>: Sets the xkb layout index for a keyboard, see wiki for details
|
flags:
|
||||||
setprop <window> <prop>: Set window property, see wiki for details
|
|
||||||
seterror <color> <msg>: Display <msg> as a error message, will reset upon reloading config
|
|
||||||
seterror disable: Clear error message
|
|
||||||
notify <icon> <time_ms> <color> <message>:
|
|
||||||
Sends a notification using the built-in Hyprland notification system.
|
|
||||||
output <args>: Add and remove fake outputs to specified backend, see wiki for details.
|
|
||||||
FLAGS:
|
|
||||||
-j -> output in JSON
|
-j -> output in JSON
|
||||||
--help -> display this help
|
-r -> refresh state after issuing command (e.g. for updating variables)
|
||||||
--batch -> execute a batch of commands, separated by ';'
|
--batch -> execute a batch of commands, separated by ';'
|
||||||
--instance (-i) -> use a specific instance. Can be either signature or index in hyprctl instances (0, 1, etc)
|
--instance (-i) -> use a specific instance. Can be either signature or index in hyprctl instances (0, 1, etc)
|
||||||
)#";
|
)#";
|
||||||
|
@ -86,7 +79,7 @@ std::vector<SInstanceData> instances() {
|
||||||
std::vector<SInstanceData> result;
|
std::vector<SInstanceData> result;
|
||||||
|
|
||||||
for (const auto& el : std::filesystem::directory_iterator("/tmp/hypr")) {
|
for (const auto& el : std::filesystem::directory_iterator("/tmp/hypr")) {
|
||||||
if (el.is_directory())
|
if (el.is_directory() || !el.path().string().ends_with(".lock"))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// read lock
|
// read lock
|
||||||
|
@ -94,7 +87,9 @@ std::vector<SInstanceData> instances() {
|
||||||
data->id = el.path().string();
|
data->id = el.path().string();
|
||||||
data->id = data->id.substr(data->id.find_last_of('/') + 1, data->id.find(".lock") - data->id.find_last_of('/') - 1);
|
data->id = data->id.substr(data->id.find_last_of('/') + 1, data->id.find(".lock") - data->id.find_last_of('/') - 1);
|
||||||
|
|
||||||
data->time = std::stoull(data->id.substr(data->id.find_first_of('_') + 1));
|
try {
|
||||||
|
data->time = std::stoull(data->id.substr(data->id.find_first_of('_') + 1));
|
||||||
|
} catch (std::exception& e) { continue; }
|
||||||
|
|
||||||
// read file
|
// read file
|
||||||
std::ifstream ifs(el.path().string());
|
std::ifstream ifs(el.path().string());
|
||||||
|
@ -102,7 +97,9 @@ std::vector<SInstanceData> instances() {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (std::string line; std::getline(ifs, line); ++i) {
|
for (std::string line; std::getline(ifs, line); ++i) {
|
||||||
if (i == 0) {
|
if (i == 0) {
|
||||||
data->pid = std::stoull(line);
|
try {
|
||||||
|
data->pid = std::stoull(line);
|
||||||
|
} catch (std::exception& e) { continue; }
|
||||||
} else if (i == 1) {
|
} else if (i == 1) {
|
||||||
data->wlSocket = line;
|
data->wlSocket = line;
|
||||||
} else
|
} else
|
||||||
|
@ -309,6 +306,8 @@ int main(int argc, char** argv) {
|
||||||
if (ARGS[i] == "-j" && !fullArgs.contains("j")) {
|
if (ARGS[i] == "-j" && !fullArgs.contains("j")) {
|
||||||
fullArgs += "j";
|
fullArgs += "j";
|
||||||
json = true;
|
json = true;
|
||||||
|
} else if (ARGS[i] == "-r" && !fullArgs.contains("r")) {
|
||||||
|
fullArgs += "r";
|
||||||
} else if (ARGS[i] == "--batch") {
|
} else if (ARGS[i] == "--batch") {
|
||||||
fullRequest = "--batch ";
|
fullRequest = "--batch ";
|
||||||
} else if (ARGS[i] == "--instance" || ARGS[i] == "-i") {
|
} else if (ARGS[i] == "--instance" || ARGS[i] == "-i") {
|
||||||
|
@ -368,7 +367,7 @@ int main(int argc, char** argv) {
|
||||||
const auto ISIG = getenv("HYPRLAND_INSTANCE_SIGNATURE");
|
const auto ISIG = getenv("HYPRLAND_INSTANCE_SIGNATURE");
|
||||||
|
|
||||||
if (!ISIG) {
|
if (!ISIG) {
|
||||||
std::cout << "HYPRLAND_INSTANCE_SIGNATURE not set! (is hyprland running?)";
|
std::cout << "HYPRLAND_INSTANCE_SIGNATURE not set! (is hyprland running?)\n";
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -379,42 +378,8 @@ int main(int argc, char** argv) {
|
||||||
|
|
||||||
if (fullRequest.contains("/--batch"))
|
if (fullRequest.contains("/--batch"))
|
||||||
batchRequest(fullRequest);
|
batchRequest(fullRequest);
|
||||||
else if (fullRequest.contains("/monitors"))
|
else if (fullRequest.contains("/hyprpaper"))
|
||||||
request(fullRequest);
|
requestHyprpaper(fullRequest);
|
||||||
else if (fullRequest.contains("/clients"))
|
|
||||||
request(fullRequest);
|
|
||||||
else if (fullRequest.contains("/workspaces"))
|
|
||||||
request(fullRequest);
|
|
||||||
else if (fullRequest.contains("/activeworkspace"))
|
|
||||||
request(fullRequest);
|
|
||||||
else if (fullRequest.contains("/workspacerules"))
|
|
||||||
request(fullRequest);
|
|
||||||
else if (fullRequest.contains("/activewindow"))
|
|
||||||
request(fullRequest);
|
|
||||||
else if (fullRequest.contains("/layers"))
|
|
||||||
request(fullRequest);
|
|
||||||
else if (fullRequest.contains("/version"))
|
|
||||||
request(fullRequest);
|
|
||||||
else if (fullRequest.contains("/kill"))
|
|
||||||
request(fullRequest);
|
|
||||||
else if (fullRequest.contains("/splash"))
|
|
||||||
request(fullRequest);
|
|
||||||
else if (fullRequest.contains("/devices"))
|
|
||||||
request(fullRequest);
|
|
||||||
else if (fullRequest.contains("/reload"))
|
|
||||||
request(fullRequest);
|
|
||||||
else if (fullRequest.contains("/getoption"))
|
|
||||||
request(fullRequest);
|
|
||||||
else if (fullRequest.contains("/binds"))
|
|
||||||
request(fullRequest);
|
|
||||||
else if (fullRequest.contains("/cursorpos"))
|
|
||||||
request(fullRequest);
|
|
||||||
else if (fullRequest.contains("/animations"))
|
|
||||||
request(fullRequest);
|
|
||||||
else if (fullRequest.contains("/globalshortcuts"))
|
|
||||||
request(fullRequest);
|
|
||||||
else if (fullRequest.contains("/rollinglog"))
|
|
||||||
request(fullRequest);
|
|
||||||
else if (fullRequest.contains("/switchxkblayout"))
|
else if (fullRequest.contains("/switchxkblayout"))
|
||||||
request(fullRequest, 2);
|
request(fullRequest, 2);
|
||||||
else if (fullRequest.contains("/seterror"))
|
else if (fullRequest.contains("/seterror"))
|
||||||
|
@ -435,15 +400,10 @@ int main(int argc, char** argv) {
|
||||||
request(fullRequest, 2);
|
request(fullRequest, 2);
|
||||||
else if (fullRequest.contains("/decorations"))
|
else if (fullRequest.contains("/decorations"))
|
||||||
request(fullRequest, 1);
|
request(fullRequest, 1);
|
||||||
else if (fullRequest.contains("/hyprpaper"))
|
|
||||||
requestHyprpaper(fullRequest);
|
|
||||||
else if (fullRequest.contains("/layouts"))
|
|
||||||
request(fullRequest);
|
|
||||||
else if (fullRequest.contains("/--help"))
|
else if (fullRequest.contains("/--help"))
|
||||||
printf("%s", USAGE.c_str());
|
printf("%s", USAGE.c_str());
|
||||||
else {
|
else {
|
||||||
printf("%s\n", USAGE.c_str());
|
request(fullRequest);
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
|
|
@ -20,11 +20,18 @@ std::string DataState::getDataStatePath() {
|
||||||
return std::string{HOME} + "/.local/share/hyprpm";
|
return std::string{HOME} + "/.local/share/hyprpm";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string DataState::getHeadersPath() {
|
||||||
|
return getDataStatePath() + "/headersRoot";
|
||||||
|
}
|
||||||
|
|
||||||
void DataState::ensureStateStoreExists() {
|
void DataState::ensureStateStoreExists() {
|
||||||
const auto PATH = getDataStatePath();
|
const auto PATH = getDataStatePath();
|
||||||
|
|
||||||
if (!std::filesystem::exists(PATH))
|
if (!std::filesystem::exists(PATH))
|
||||||
std::filesystem::create_directories(PATH);
|
std::filesystem::create_directories(PATH);
|
||||||
|
|
||||||
|
if (!std::filesystem::exists(getHeadersPath()))
|
||||||
|
std::filesystem::create_directories(getHeadersPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
void DataState::addNewPluginRepo(const SPluginRepository& repo) {
|
void DataState::addNewPluginRepo(const SPluginRepository& repo) {
|
||||||
|
@ -47,7 +54,8 @@ void DataState::addNewPluginRepo(const SPluginRepository& repo) {
|
||||||
|
|
||||||
DATA.emplace(p.name, toml::table{
|
DATA.emplace(p.name, toml::table{
|
||||||
{"filename", p.name + ".so"},
|
{"filename", p.name + ".so"},
|
||||||
{"enabled", p.enabled}
|
{"enabled", p.enabled},
|
||||||
|
{"failed", p.failed}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
@ -63,7 +71,10 @@ bool DataState::pluginRepoExists(const std::string& urlOrName) {
|
||||||
const auto PATH = getDataStatePath();
|
const auto PATH = getDataStatePath();
|
||||||
|
|
||||||
for (const auto& entry : std::filesystem::directory_iterator(PATH)) {
|
for (const auto& entry : std::filesystem::directory_iterator(PATH)) {
|
||||||
if (!entry.is_directory())
|
if (!entry.is_directory() || entry.path().stem() == "headersRoot")
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!std::filesystem::exists(entry.path().string() + "/state.toml"))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
auto STATE = toml::parse_file(entry.path().string() + "/state.toml");
|
auto STATE = toml::parse_file(entry.path().string() + "/state.toml");
|
||||||
|
@ -84,7 +95,10 @@ void DataState::removePluginRepo(const std::string& urlOrName) {
|
||||||
const auto PATH = getDataStatePath();
|
const auto PATH = getDataStatePath();
|
||||||
|
|
||||||
for (const auto& entry : std::filesystem::directory_iterator(PATH)) {
|
for (const auto& entry : std::filesystem::directory_iterator(PATH)) {
|
||||||
if (!entry.is_directory())
|
if (!entry.is_directory() || entry.path().stem() == "headersRoot")
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!std::filesystem::exists(entry.path().string() + "/state.toml"))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
auto STATE = toml::parse_file(entry.path().string() + "/state.toml");
|
auto STATE = toml::parse_file(entry.path().string() + "/state.toml");
|
||||||
|
@ -153,7 +167,10 @@ std::vector<SPluginRepository> DataState::getAllRepositories() {
|
||||||
std::vector<SPluginRepository> repos;
|
std::vector<SPluginRepository> repos;
|
||||||
|
|
||||||
for (const auto& entry : std::filesystem::directory_iterator(PATH)) {
|
for (const auto& entry : std::filesystem::directory_iterator(PATH)) {
|
||||||
if (!entry.is_directory())
|
if (!entry.is_directory() || entry.path().stem() == "headersRoot")
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!std::filesystem::exists(entry.path().string() + "/state.toml"))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
auto STATE = toml::parse_file(entry.path().string() + "/state.toml");
|
auto STATE = toml::parse_file(entry.path().string() + "/state.toml");
|
||||||
|
@ -172,9 +189,10 @@ std::vector<SPluginRepository> DataState::getAllRepositories() {
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const auto ENABLED = STATE[key]["enabled"].value_or(false);
|
const auto ENABLED = STATE[key]["enabled"].value_or(false);
|
||||||
|
const auto FAILED = STATE[key]["failed"].value_or(false);
|
||||||
const auto FILENAME = STATE[key]["filename"].value_or("");
|
const auto FILENAME = STATE[key]["filename"].value_or("");
|
||||||
|
|
||||||
repo.plugins.push_back(SPlugin{std::string{key.str()}, FILENAME, ENABLED});
|
repo.plugins.push_back(SPlugin{std::string{key.str()}, FILENAME, ENABLED, FAILED});
|
||||||
}
|
}
|
||||||
|
|
||||||
repos.push_back(repo);
|
repos.push_back(repo);
|
||||||
|
@ -189,7 +207,10 @@ bool DataState::setPluginEnabled(const std::string& name, bool enabled) {
|
||||||
const auto PATH = getDataStatePath();
|
const auto PATH = getDataStatePath();
|
||||||
|
|
||||||
for (const auto& entry : std::filesystem::directory_iterator(PATH)) {
|
for (const auto& entry : std::filesystem::directory_iterator(PATH)) {
|
||||||
if (!entry.is_directory())
|
if (!entry.is_directory() || entry.path().stem() == "headersRoot")
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!std::filesystem::exists(entry.path().string() + "/state.toml"))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
auto STATE = toml::parse_file(entry.path().string() + "/state.toml");
|
auto STATE = toml::parse_file(entry.path().string() + "/state.toml");
|
||||||
|
@ -201,6 +222,11 @@ bool DataState::setPluginEnabled(const std::string& name, bool enabled) {
|
||||||
if (key.str() != name)
|
if (key.str() != name)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
const auto FAILED = STATE[key]["failed"].value_or(false);
|
||||||
|
|
||||||
|
if (FAILED)
|
||||||
|
return false;
|
||||||
|
|
||||||
(*STATE[key].as_table()).insert_or_assign("enabled", enabled);
|
(*STATE[key].as_table()).insert_or_assign("enabled", enabled);
|
||||||
|
|
||||||
std::ofstream state(entry.path().string() + "/state.toml", std::ios::trunc);
|
std::ofstream state(entry.path().string() + "/state.toml", std::ios::trunc);
|
||||||
|
|
|
@ -10,6 +10,7 @@ struct SGlobalState {
|
||||||
|
|
||||||
namespace DataState {
|
namespace DataState {
|
||||||
std::string getDataStatePath();
|
std::string getDataStatePath();
|
||||||
|
std::string getHeadersPath();
|
||||||
void ensureStateStoreExists();
|
void ensureStateStoreExists();
|
||||||
void addNewPluginRepo(const SPluginRepository& repo);
|
void addNewPluginRepo(const SPluginRepository& repo);
|
||||||
void removePluginRepo(const std::string& urlOrName);
|
void removePluginRepo(const std::string& urlOrName);
|
||||||
|
|
|
@ -19,6 +19,7 @@ class CManifest {
|
||||||
std::vector<std::string> authors;
|
std::vector<std::string> authors;
|
||||||
std::vector<std::string> buildSteps;
|
std::vector<std::string> buildSteps;
|
||||||
std::string output;
|
std::string output;
|
||||||
|
bool failed = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
|
|
|
@ -6,7 +6,8 @@
|
||||||
struct SPlugin {
|
struct SPlugin {
|
||||||
std::string name;
|
std::string name;
|
||||||
std::string filename;
|
std::string filename;
|
||||||
bool enabled;
|
bool enabled = false;
|
||||||
|
bool failed = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SPluginRepository {
|
struct SPluginRepository {
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <format>
|
||||||
|
|
||||||
#include <toml++/toml.hpp>
|
#include <toml++/toml.hpp>
|
||||||
|
|
||||||
|
@ -78,6 +79,8 @@ SHyprlandVersion CPluginManager::getHyprlandVersion() {
|
||||||
|
|
||||||
bool CPluginManager::addNewPluginRepo(const std::string& url) {
|
bool CPluginManager::addNewPluginRepo(const std::string& url) {
|
||||||
|
|
||||||
|
const auto HLVER = getHyprlandVersion();
|
||||||
|
|
||||||
if (DataState::pluginRepoExists(url)) {
|
if (DataState::pluginRepoExists(url)) {
|
||||||
std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " Could not clone the plugin repository. Repository already installed.\n";
|
std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " Could not clone the plugin repository. Repository already installed.\n";
|
||||||
return false;
|
return false;
|
||||||
|
@ -170,6 +173,22 @@ bool CPluginManager::addNewPluginRepo(const std::string& url) {
|
||||||
message += " version " + pl.version;
|
message += " version " + pl.version;
|
||||||
progress.printMessageAbove(message);
|
progress.printMessageAbove(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!pManifest->m_sRepository.commitPins.empty()) {
|
||||||
|
// check commit pins
|
||||||
|
|
||||||
|
progress.printMessageAbove(std::string{Colors::RESET} + " → Manifest has " + std::to_string(pManifest->m_sRepository.commitPins.size()) + " pins, checking");
|
||||||
|
|
||||||
|
for (auto& [hl, plugin] : pManifest->m_sRepository.commitPins) {
|
||||||
|
if (hl != HLVER.hash)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " commit pin " + plugin + " matched hl, resetting");
|
||||||
|
|
||||||
|
execAndGet("cd /tmp/hyprpm/new/ && git reset --hard --recurse-submodules " + plugin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
progress.m_szCurrentMessage = "Verifying headers";
|
progress.m_szCurrentMessage = "Verifying headers";
|
||||||
progress.print();
|
progress.print();
|
||||||
|
|
||||||
|
@ -191,16 +210,19 @@ bool CPluginManager::addNewPluginRepo(const std::string& url) {
|
||||||
progress.printMessageAbove(std::string{Colors::RESET} + " → Building " + p.name);
|
progress.printMessageAbove(std::string{Colors::RESET} + " → Building " + p.name);
|
||||||
|
|
||||||
for (auto& bs : p.buildSteps) {
|
for (auto& bs : p.buildSteps) {
|
||||||
out += execAndGet("cd /tmp/hyprpm/new && " + bs) + "\n";
|
std::string cmd = std::format("cd /tmp/hyprpm/new && PKG_CONFIG_PATH=\"{}/share/pkgconfig\" {}", DataState::getHeadersPath(), bs);
|
||||||
|
out += " -> " + cmd + "\n" + execAndGet(cmd) + "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!std::filesystem::exists("/tmp/hyprpm/new/" + p.output)) {
|
if (!std::filesystem::exists("/tmp/hyprpm/new/" + p.output)) {
|
||||||
std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " Plugin " << p.name << " failed to build.\n";
|
progress.printMessageAbove(std::string{Colors::RED} + "✖" + Colors::RESET + " Plugin " + p.name + " failed to build.\n");
|
||||||
|
|
||||||
if (m_bVerbose)
|
if (m_bVerbose)
|
||||||
std::cout << Colors::BLUE << "[v] " << Colors::RESET << "shell returned: " << out << "\n";
|
std::cout << Colors::BLUE << "[v] " << Colors::RESET << "shell returned: " << out << "\n";
|
||||||
|
|
||||||
return false;
|
p.failed = true;
|
||||||
|
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " built " + p.name + " into " + p.output);
|
progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " built " + p.name + " into " + p.output);
|
||||||
|
@ -220,7 +242,7 @@ bool CPluginManager::addNewPluginRepo(const std::string& url) {
|
||||||
repo.url = url;
|
repo.url = url;
|
||||||
repo.hash = repohash;
|
repo.hash = repohash;
|
||||||
for (auto& p : pManifest->m_vPlugins) {
|
for (auto& p : pManifest->m_vPlugins) {
|
||||||
repo.plugins.push_back(SPlugin{p.name, "/tmp/hyprpm/new/" + p.output, false});
|
repo.plugins.push_back(SPlugin{p.name, "/tmp/hyprpm/new/" + p.output, false, p.failed});
|
||||||
}
|
}
|
||||||
DataState::addNewPluginRepo(repo);
|
DataState::addNewPluginRepo(repo);
|
||||||
|
|
||||||
|
@ -263,8 +285,12 @@ bool CPluginManager::removePluginRepo(const std::string& urlOrName) {
|
||||||
eHeadersErrors CPluginManager::headersValid() {
|
eHeadersErrors CPluginManager::headersValid() {
|
||||||
const auto HLVER = getHyprlandVersion();
|
const auto HLVER = getHyprlandVersion();
|
||||||
|
|
||||||
|
if (!std::filesystem::exists(DataState::getHeadersPath() + "/share/pkgconfig/hyprland.pc"))
|
||||||
|
return HEADERS_MISSING;
|
||||||
|
|
||||||
// find headers commit
|
// find headers commit
|
||||||
auto headers = execAndGet("pkg-config --cflags --keep-system-cflags hyprland");
|
std::string cmd = std::format("PKG_CONFIG_PATH=\"{}/share/pkgconfig\" pkg-config --cflags --keep-system-cflags hyprland", DataState::getHeadersPath());
|
||||||
|
auto headers = execAndGet(cmd.c_str());
|
||||||
|
|
||||||
if (!headers.contains("-I/"))
|
if (!headers.contains("-I/"))
|
||||||
return HEADERS_MISSING;
|
return HEADERS_MISSING;
|
||||||
|
@ -296,10 +322,6 @@ eHeadersErrors CPluginManager::headersValid() {
|
||||||
if (!ifs.good())
|
if (!ifs.good())
|
||||||
return HEADERS_CORRUPTED;
|
return HEADERS_CORRUPTED;
|
||||||
|
|
||||||
if ((std::filesystem::exists("/usr/include/hyprland/src/version.h") && verHeader != "/usr/include/hyprland/src/version.h") ||
|
|
||||||
(std::filesystem::exists("/usr/local/include/hyprland/src/version.h") && verHeader != "/usr/local/include/hyprland/src/version.h"))
|
|
||||||
return HEADERS_DUPLICATED;
|
|
||||||
|
|
||||||
std::string verHeaderContent((std::istreambuf_iterator<char>(ifs)), (std::istreambuf_iterator<char>()));
|
std::string verHeaderContent((std::istreambuf_iterator<char>(ifs)), (std::istreambuf_iterator<char>()));
|
||||||
ifs.close();
|
ifs.close();
|
||||||
|
|
||||||
|
@ -314,7 +336,9 @@ eHeadersErrors CPluginManager::headersValid() {
|
||||||
return HEADERS_OK;
|
return HEADERS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CPluginManager::updateHeaders() {
|
bool CPluginManager::updateHeaders(bool force) {
|
||||||
|
|
||||||
|
DataState::ensureStateStoreExists();
|
||||||
|
|
||||||
const auto HLVER = getHyprlandVersion();
|
const auto HLVER = getHyprlandVersion();
|
||||||
|
|
||||||
|
@ -323,11 +347,8 @@ bool CPluginManager::updateHeaders() {
|
||||||
std::filesystem::permissions("/tmp/hyprpm", std::filesystem::perms::all, std::filesystem::perm_options::replace);
|
std::filesystem::permissions("/tmp/hyprpm", std::filesystem::perms::all, std::filesystem::perm_options::replace);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (headersValid() == HEADERS_OK) {
|
if (!force && headersValid() == HEADERS_OK) {
|
||||||
std::cout << "\n" << std::string{Colors::GREEN} + "✔" + Colors::RESET + " Your headers are already up-to-date.\n";
|
std::cout << "\n" << std::string{Colors::GREEN} + "✔" + Colors::RESET + " Headers up to date.\n";
|
||||||
auto GLOBALSTATE = DataState::getGlobalState();
|
|
||||||
GLOBALSTATE.headersHashCompiled = HLVER.hash;
|
|
||||||
DataState::updateGlobalState(GLOBALSTATE);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -342,9 +363,9 @@ bool CPluginManager::updateHeaders() {
|
||||||
std::filesystem::remove_all("/tmp/hyprpm/hyprland");
|
std::filesystem::remove_all("/tmp/hyprpm/hyprland");
|
||||||
}
|
}
|
||||||
|
|
||||||
progress.printMessageAbove(std::string{Colors::YELLOW} + "!" + Colors::RESET + " Cloning https://github.com/dragontos/hyprland, this might take a moment.");
|
progress.printMessageAbove(std::string{Colors::YELLOW} + "!" + Colors::RESET + " Cloning https://github.com/hyprwm/hyprland, this might take a moment.");
|
||||||
|
|
||||||
std::string ret = execAndGet("cd /tmp/hyprpm && git clone --recursive https://github.com/dragontos/hyprland hyprland");
|
std::string ret = execAndGet("cd /tmp/hyprpm && git clone --recursive https://github.com/hyprwm/hyprland hyprland");
|
||||||
|
|
||||||
if (!std::filesystem::exists("/tmp/hyprpm/hyprland")) {
|
if (!std::filesystem::exists("/tmp/hyprpm/hyprland")) {
|
||||||
std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " Could not clone the hyprland repository. shell returned:\n" << ret << "\n";
|
std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " Could not clone the hyprland repository. shell returned:\n" << ret << "\n";
|
||||||
|
@ -369,23 +390,38 @@ bool CPluginManager::updateHeaders() {
|
||||||
|
|
||||||
progress.printMessageAbove(std::string{Colors::YELLOW} + "!" + Colors::RESET + " configuring Hyprland");
|
progress.printMessageAbove(std::string{Colors::YELLOW} + "!" + Colors::RESET + " configuring Hyprland");
|
||||||
|
|
||||||
ret = execAndGet("cd /tmp/hyprpm/hyprland && cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -S . -B ./build -G Ninja");
|
if (m_bVerbose)
|
||||||
|
progress.printMessageAbove(std::string{Colors::BLUE} + "[v] " + Colors::RESET + "setting PREFIX for cmake to " + DataState::getHeadersPath());
|
||||||
|
|
||||||
|
ret = execAndGet(
|
||||||
|
std::format("cd /tmp/hyprpm/hyprland && cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:STRING=\"{}\" -S . -B ./build -G Ninja",
|
||||||
|
DataState::getHeadersPath()));
|
||||||
|
if (m_bVerbose)
|
||||||
|
progress.printMessageAbove(std::string{Colors::BLUE} + "[v] " + Colors::RESET + "cmake returned: " + ret);
|
||||||
|
|
||||||
// le hack. Wlroots has to generate its build/include
|
// le hack. Wlroots has to generate its build/include
|
||||||
ret = execAndGet("cd /tmp/hyprpm/hyprland/subprojects/wlroots && meson setup -Drenderers=gles2 -Dexamples=false build");
|
ret = execAndGet("cd /tmp/hyprpm/hyprland/subprojects/wlroots && meson setup -Drenderers=gles2 -Dexamples=false build");
|
||||||
|
if (m_bVerbose)
|
||||||
|
progress.printMessageAbove(std::string{Colors::BLUE} + "[v] " + Colors::RESET + "meson returned: " + ret);
|
||||||
|
|
||||||
progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " configured Hyprland");
|
progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " configured Hyprland");
|
||||||
progress.m_iSteps = 4;
|
progress.m_iSteps = 4;
|
||||||
progress.m_szCurrentMessage = "Installing sources";
|
progress.m_szCurrentMessage = "Installing sources";
|
||||||
progress.print();
|
progress.print();
|
||||||
|
|
||||||
progress.printMessageAbove(
|
// progress.printMessageAbove(
|
||||||
std::string{Colors::YELLOW} + "!" + Colors::RESET +
|
// std::string{Colors::YELLOW} + "!" + Colors::RESET +
|
||||||
" in order to install the sources, you will need to input your password.\n If nothing pops up, make sure you have polkit and an authentication daemon running.");
|
// " in order to install the sources, you will need to input your password.\n If nothing pops up, make sure you have polkit and an authentication daemon running.");
|
||||||
|
|
||||||
ret = execAndGet("pkexec sh \"-c\" \"cd /tmp/hyprpm/hyprland && make installheaders\"");
|
std::string cmd = std::format("sed -i -e \"s#PREFIX = /usr/local#PREFIX = {}#\" /tmp/hyprpm/hyprland/Makefile && cd /tmp/hyprpm/hyprland && make installheaders",
|
||||||
|
DataState::getHeadersPath());
|
||||||
|
if (m_bVerbose)
|
||||||
|
progress.printMessageAbove(std::string{Colors::BLUE} + "[v] " + Colors::RESET + "installation will run: " + cmd);
|
||||||
|
|
||||||
|
ret = execAndGet(cmd);
|
||||||
|
|
||||||
if (m_bVerbose)
|
if (m_bVerbose)
|
||||||
std::cout << Colors::BLUE << "[v] " << Colors::RESET << "pkexec returned: " << ret << "\n";
|
std::cout << Colors::BLUE << "[v] " << Colors::RESET << "installer returned: " << ret << "\n";
|
||||||
|
|
||||||
// remove build files
|
// remove build files
|
||||||
std::filesystem::remove_all("/tmp/hyprpm/hyprland");
|
std::filesystem::remove_all("/tmp/hyprpm/hyprland");
|
||||||
|
@ -397,10 +433,6 @@ bool CPluginManager::updateHeaders() {
|
||||||
progress.m_szCurrentMessage = "Done!";
|
progress.m_szCurrentMessage = "Done!";
|
||||||
progress.print();
|
progress.print();
|
||||||
|
|
||||||
auto GLOBALSTATE = DataState::getGlobalState();
|
|
||||||
GLOBALSTATE.headersHashCompiled = HLVER.hash;
|
|
||||||
DataState::updateGlobalState(GLOBALSTATE);
|
|
||||||
|
|
||||||
std::cout << "\n";
|
std::cout << "\n";
|
||||||
} else {
|
} else {
|
||||||
progress.printMessageAbove(std::string{Colors::RED} + "✖" + Colors::RESET + " failed to install headers with error code " + std::to_string((int)HEADERSVALID));
|
progress.printMessageAbove(std::string{Colors::RED} + "✖" + Colors::RESET + " failed to install headers with error code " + std::to_string((int)HEADERSVALID));
|
||||||
|
@ -434,7 +466,7 @@ bool CPluginManager::updatePlugins(bool forceUpdateAll) {
|
||||||
const auto HLVER = getHyprlandVersion();
|
const auto HLVER = getHyprlandVersion();
|
||||||
|
|
||||||
CProgressBar progress;
|
CProgressBar progress;
|
||||||
progress.m_iMaxSteps = REPOS.size() * 2 + 1;
|
progress.m_iMaxSteps = REPOS.size() * 2 + 2;
|
||||||
progress.m_iSteps = 0;
|
progress.m_iSteps = 0;
|
||||||
progress.m_szCurrentMessage = "Updating repositories";
|
progress.m_szCurrentMessage = "Updating repositories";
|
||||||
progress.print();
|
progress.print();
|
||||||
|
@ -528,7 +560,8 @@ bool CPluginManager::updatePlugins(bool forceUpdateAll) {
|
||||||
progress.printMessageAbove(std::string{Colors::RESET} + " → Building " + p.name);
|
progress.printMessageAbove(std::string{Colors::RESET} + " → Building " + p.name);
|
||||||
|
|
||||||
for (auto& bs : p.buildSteps) {
|
for (auto& bs : p.buildSteps) {
|
||||||
out += execAndGet("cd /tmp/hyprpm/update && " + bs) + "\n";
|
std::string cmd = std::format("cd /tmp/hyprpm/update && PKG_CONFIG_PATH=\"{}/share/pkgconfig\" {}", DataState::getHeadersPath(), bs);
|
||||||
|
out += " -> " + cmd + "\n" + execAndGet(cmd) + "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!std::filesystem::exists("/tmp/hyprpm/update/" + p.output)) {
|
if (!std::filesystem::exists("/tmp/hyprpm/update/" + p.output)) {
|
||||||
|
@ -566,6 +599,14 @@ bool CPluginManager::updatePlugins(bool forceUpdateAll) {
|
||||||
progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " updated " + repo.name);
|
progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " updated " + repo.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
progress.m_iSteps++;
|
||||||
|
progress.m_szCurrentMessage = "Updating global state...";
|
||||||
|
progress.print();
|
||||||
|
|
||||||
|
auto GLOBALSTATE = DataState::getGlobalState();
|
||||||
|
GLOBALSTATE.headersHashCompiled = HLVER.hash;
|
||||||
|
DataState::updateGlobalState(GLOBALSTATE);
|
||||||
|
|
||||||
progress.m_iSteps++;
|
progress.m_iSteps++;
|
||||||
progress.m_szCurrentMessage = "Done!";
|
progress.m_szCurrentMessage = "Done!";
|
||||||
progress.print();
|
progress.print();
|
||||||
|
@ -696,8 +737,13 @@ void CPluginManager::listAllPlugins() {
|
||||||
std::cout << std::string{Colors::RESET} + " → Repository " + r.name + ":\n";
|
std::cout << std::string{Colors::RESET} + " → Repository " + r.name + ":\n";
|
||||||
|
|
||||||
for (auto& p : r.plugins) {
|
for (auto& p : r.plugins) {
|
||||||
std::cout << std::string{Colors::RESET} + " │ Plugin " + p.name + "\n └─ enabled: " << (p.enabled ? Colors::GREEN : Colors::RED) << (p.enabled ? "true" : "false")
|
|
||||||
<< Colors::RESET << "\n";
|
std::cout << std::string{Colors::RESET} + " │ Plugin " + p.name;
|
||||||
|
|
||||||
|
if (!p.failed)
|
||||||
|
std::cout << "\n └─ enabled: " << (p.enabled ? Colors::GREEN : Colors::RED) << (p.enabled ? "true" : "false") << Colors::RESET << "\n";
|
||||||
|
else
|
||||||
|
std::cout << "\n └─ enabled: " << Colors::RED << "Plugin failed to build" << Colors::RESET << "\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,7 +40,7 @@ class CPluginManager {
|
||||||
bool removePluginRepo(const std::string& urlOrName);
|
bool removePluginRepo(const std::string& urlOrName);
|
||||||
|
|
||||||
eHeadersErrors headersValid();
|
eHeadersErrors headersValid();
|
||||||
bool updateHeaders();
|
bool updateHeaders(bool force = false);
|
||||||
bool updatePlugins(bool forceUpdateAll);
|
bool updatePlugins(bool forceUpdateAll);
|
||||||
|
|
||||||
void listAllPlugins();
|
void listAllPlugins();
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#include "progress/CProgressBar.hpp"
|
#include "progress/CProgressBar.hpp"
|
||||||
#include "helpers/Colors.hpp"
|
#include "helpers/Colors.hpp"
|
||||||
#include "core/PluginManager.hpp"
|
#include "core/PluginManager.hpp"
|
||||||
|
#include "core/DataState.hpp"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
@ -8,21 +9,23 @@
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
const std::string HELP = R"#(usage: hyprpm [flags] [<command> [args]]
|
const std::string HELP = R"#(┏ hyprpm, a Hyprland Plugin Manager
|
||||||
|
┃
|
||||||
LISTING COMMANDS:
|
┣ add [url] → Install a new plugin repository from git
|
||||||
add: Install a new plugin repository from git
|
┣ remove [url/name] → Remove an installed plugin repository
|
||||||
remove: Remove an installed plugin repository
|
┣ enable [name] → Enable a plugin
|
||||||
enable: Enable a plugin
|
┣ disable [name] → Disable a plugin
|
||||||
disable: Disable a plugin
|
┣ update → Check and update all plugins if needed
|
||||||
update: Check and update all plugins if needed
|
┣ reload → Reload hyprpm state. Ensure all enabled plugins are loaded.
|
||||||
reload: Rreload hyprpm state. Ensure all enabled plugins are loaded.
|
┣ list → List all installed plugins
|
||||||
list: List all installed plugins
|
┃
|
||||||
FLAGS:
|
┣ Flags:
|
||||||
--notify -> Send a hyprland notification for important events (e.g. load fail)
|
┃
|
||||||
--help -> display this help
|
┣ --notify | -n → Send a hyprland notification for important events (e.g. load fail)
|
||||||
--verbose -> Enable too much logging
|
┣ --help | -h → Show this menu
|
||||||
|
┣ --verbose | -v → Enable too much logging
|
||||||
|
┣ --force | -f → Force an operation ignoring checks (e.g. update -f)
|
||||||
|
┗
|
||||||
)#";
|
)#";
|
||||||
|
|
||||||
int main(int argc, char** argv, char** envp) {
|
int main(int argc, char** argv, char** envp) {
|
||||||
|
@ -37,7 +40,7 @@ int main(int argc, char** argv, char** envp) {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> command;
|
std::vector<std::string> command;
|
||||||
bool notify = false, verbose = false;
|
bool notify = false, verbose = false, force = false;
|
||||||
|
|
||||||
for (int i = 1; i < argc; ++i) {
|
for (int i = 1; i < argc; ++i) {
|
||||||
if (ARGS[i].starts_with("-")) {
|
if (ARGS[i].starts_with("-")) {
|
||||||
|
@ -48,6 +51,9 @@ int main(int argc, char** argv, char** envp) {
|
||||||
notify = true;
|
notify = true;
|
||||||
} else if (ARGS[i] == "--verbose" || ARGS[i] == "-v") {
|
} else if (ARGS[i] == "--verbose" || ARGS[i] == "-v") {
|
||||||
verbose = true;
|
verbose = true;
|
||||||
|
} else if (ARGS[i] == "--force" || ARGS[i] == "-f") {
|
||||||
|
force = true;
|
||||||
|
std::cout << Colors::RED << "!" << Colors::RESET << " Using --force, I hope you know what you are doing.\n";
|
||||||
} else {
|
} else {
|
||||||
std::cerr << "Unrecognized option " << ARGS[i];
|
std::cerr << "Unrecognized option " << ARGS[i];
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -81,9 +87,13 @@ int main(int argc, char** argv, char** envp) {
|
||||||
return g_pPluginManager->removePluginRepo(command[1]) ? 0 : 1;
|
return g_pPluginManager->removePluginRepo(command[1]) ? 0 : 1;
|
||||||
} else if (command[0] == "update") {
|
} else if (command[0] == "update") {
|
||||||
bool headersValid = g_pPluginManager->headersValid() == HEADERS_OK;
|
bool headersValid = g_pPluginManager->headersValid() == HEADERS_OK;
|
||||||
bool headers = g_pPluginManager->updateHeaders();
|
bool headers = g_pPluginManager->updateHeaders(force);
|
||||||
if (headers) {
|
if (headers) {
|
||||||
bool ret1 = g_pPluginManager->updatePlugins(!headersValid);
|
const auto HLVER = g_pPluginManager->getHyprlandVersion();
|
||||||
|
auto GLOBALSTATE = DataState::getGlobalState();
|
||||||
|
const auto COMPILEDOUTDATED = HLVER.hash != GLOBALSTATE.headersHashCompiled;
|
||||||
|
|
||||||
|
bool ret1 = g_pPluginManager->updatePlugins(!headersValid || force || COMPILEDOUTDATED);
|
||||||
|
|
||||||
if (!ret1)
|
if (!ret1)
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -145,4 +155,4 @@ int main(int argc, char** argv, char** envp) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
|
@ -9,6 +9,7 @@
|
||||||
cairo,
|
cairo,
|
||||||
git,
|
git,
|
||||||
hyprland-protocols,
|
hyprland-protocols,
|
||||||
|
hyprlang,
|
||||||
jq,
|
jq,
|
||||||
libGL,
|
libGL,
|
||||||
libdrm,
|
libdrm,
|
||||||
|
@ -75,6 +76,7 @@ assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been remov
|
||||||
cairo
|
cairo
|
||||||
git
|
git
|
||||||
hyprland-protocols
|
hyprland-protocols
|
||||||
|
hyprlang
|
||||||
libdrm
|
libdrm
|
||||||
libGL
|
libGL
|
||||||
libinput
|
libinput
|
||||||
|
|
|
@ -10,21 +10,19 @@
|
||||||
(builtins.substring 4 2 longDate)
|
(builtins.substring 4 2 longDate)
|
||||||
(builtins.substring 6 2 longDate)
|
(builtins.substring 6 2 longDate)
|
||||||
]);
|
]);
|
||||||
|
|
||||||
mkJoinedOverlays = overlays: final: prev:
|
|
||||||
lib.foldl' (attrs: overlay: attrs // (overlay final prev)) {} overlays;
|
|
||||||
in {
|
in {
|
||||||
# Contains what a user is most likely to care about:
|
# Contains what a user is most likely to care about:
|
||||||
# Hyprland itself, XDPH and the Share Picker.
|
# Hyprland itself, XDPH and the Share Picker.
|
||||||
default = mkJoinedOverlays (with self.overlays; [
|
default = lib.composeManyExtensions (with self.overlays; [
|
||||||
hyprland-packages
|
hyprland-packages
|
||||||
hyprland-extras
|
hyprland-extras
|
||||||
]);
|
]);
|
||||||
|
|
||||||
# Packages for variations of Hyprland, dependencies included.
|
# Packages for variations of Hyprland, dependencies included.
|
||||||
hyprland-packages = mkJoinedOverlays [
|
hyprland-packages = lib.composeManyExtensions [
|
||||||
# Dependencies
|
# Dependencies
|
||||||
inputs.hyprland-protocols.overlays.default
|
inputs.hyprland-protocols.overlays.default
|
||||||
|
inputs.hyprlang.overlays.default
|
||||||
self.overlays.wlroots-hyprland
|
self.overlays.wlroots-hyprland
|
||||||
self.overlays.udis86
|
self.overlays.udis86
|
||||||
# Hyprland packages themselves
|
# Hyprland packages themselves
|
||||||
|
@ -34,9 +32,9 @@ in {
|
||||||
hyprland = final.callPackage ./default.nix {
|
hyprland = final.callPackage ./default.nix {
|
||||||
stdenv = final.gcc13Stdenv;
|
stdenv = final.gcc13Stdenv;
|
||||||
version = "${props.version}+date=${date}_${self.shortRev or "dirty"}";
|
version = "${props.version}+date=${date}_${self.shortRev or "dirty"}";
|
||||||
wlroots = final.wlroots-hyprland;
|
|
||||||
commit = self.rev or "";
|
commit = self.rev or "";
|
||||||
inherit (final) udis86 hyprland-protocols;
|
wlroots = final.wlroots-hyprland; # explicit override until decided on breaking change of the name
|
||||||
|
udis86 = final.udis86-hyprland; # explicit override until decided on breaking change of the name
|
||||||
inherit date;
|
inherit date;
|
||||||
};
|
};
|
||||||
hyprland-unwrapped = final.hyprland.override {wrapRuntimeDeps = false;};
|
hyprland-unwrapped = final.hyprland.override {wrapRuntimeDeps = false;};
|
||||||
|
@ -59,12 +57,12 @@ in {
|
||||||
|
|
||||||
# Packages for extra software recommended for usage with Hyprland,
|
# Packages for extra software recommended for usage with Hyprland,
|
||||||
# including forked or patched packages for compatibility.
|
# including forked or patched packages for compatibility.
|
||||||
hyprland-extras = mkJoinedOverlays [
|
hyprland-extras = lib.composeManyExtensions [
|
||||||
inputs.xdph.overlays.xdg-desktop-portal-hyprland
|
inputs.xdph.overlays.xdg-desktop-portal-hyprland
|
||||||
];
|
];
|
||||||
|
|
||||||
udis86 = final: prev: {
|
udis86 = final: prev: {
|
||||||
udis86 = final.callPackage ./udis86.nix {};
|
udis86-hyprland = final.callPackage ./udis86.nix {};
|
||||||
};
|
};
|
||||||
|
|
||||||
# Patched version of wlroots for Hyprland.
|
# Patched version of wlroots for Hyprland.
|
||||||
|
|
|
@ -34,16 +34,17 @@ index 1d2c7f9f..c5ef4e67 100644
|
||||||
headers = globber.stdout().strip().split('\n')
|
headers = globber.stdout().strip().split('\n')
|
||||||
foreach file : headers
|
foreach file : headers
|
||||||
diff --git a/src/meson.build b/src/meson.build
|
diff --git a/src/meson.build b/src/meson.build
|
||||||
index 0af864b9..38723b8c 100644
|
index 45701f5f..3505cefe 100644
|
||||||
--- a/src/meson.build
|
--- a/src/meson.build
|
||||||
+++ b/src/meson.build
|
+++ b/src/meson.build
|
||||||
@@ -9,16 +9,16 @@ executable('Hyprland', src,
|
@@ -9,17 +9,17 @@ executable('Hyprland', src,
|
||||||
server_protos,
|
server_protos,
|
||||||
dependency('wayland-server'),
|
dependency('wayland-server'),
|
||||||
dependency('wayland-client'),
|
dependency('wayland-client'),
|
||||||
- wlroots.get_variable('wlroots'),
|
- wlroots.get_variable('wlroots'),
|
||||||
+ dependency('wlroots'),
|
+ dependency('wlroots'),
|
||||||
dependency('cairo'),
|
dependency('cairo'),
|
||||||
|
dependency('hyprlang', version: '>= 0.3.2'),
|
||||||
dependency('libdrm'),
|
dependency('libdrm'),
|
||||||
dependency('egl'),
|
dependency('egl'),
|
||||||
dependency('xkbcommon'),
|
dependency('xkbcommon'),
|
||||||
|
|
|
@ -8,7 +8,7 @@ CRT_REV=$(rg rev flake.nix | awk '{ print substr($3, 2, 40) }')
|
||||||
if [ "$SUB_REV" != "$CRT_REV" ]; then
|
if [ "$SUB_REV" != "$CRT_REV" ]; then
|
||||||
echo "Updating wlroots..."
|
echo "Updating wlroots..."
|
||||||
# update wlroots to submodule revision
|
# update wlroots to submodule revision
|
||||||
sed -Ei "s/\w{40}/$SUB_REV/g" flake.nix subprojects/wlroots.wrap
|
sed -Ei "s/\w{40}/$SUB_REV/g" flake.nix
|
||||||
nix flake lock
|
nix flake lock
|
||||||
|
|
||||||
echo "wlroots: $CRT_REV -> $SUB_REV"
|
echo "wlroots: $CRT_REV -> $SUB_REV"
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
{
|
{
|
||||||
"version": "0.34.0"
|
"version": "0.36.0"
|
||||||
}
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
wayland_protos = dependency('wayland-protocols',
|
wayland_protos = dependency('wayland-protocols',
|
||||||
version: '>=1.25',
|
version: '>=1.32',
|
||||||
fallback: 'wayland-protocols',
|
fallback: 'wayland-protocols',
|
||||||
default_options: ['tests=false'],
|
default_options: ['tests=false'],
|
||||||
)
|
)
|
||||||
|
|
21
scripts/hyprlandStaticAsan.diff
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
diff --git a/CMakeLists.txt b/CMakeLists.txt
|
||||||
|
index 857e21de..122d6a78 100755
|
||||||
|
--- a/CMakeLists.txt
|
||||||
|
+++ b/CMakeLists.txt
|
||||||
|
@@ -101,7 +101,7 @@ message(STATUS "Checking deps...")
|
||||||
|
find_package(Threads REQUIRED)
|
||||||
|
find_package(PkgConfig REQUIRED)
|
||||||
|
find_package(OpenGL REQUIRED)
|
||||||
|
-pkg_check_modules(deps REQUIRED IMPORTED_TARGET wayland-server wayland-client wayland-cursor wayland-protocols cairo libdrm xkbcommon libinput pango pangocairo pixman-1 hyprlang>=0.3.2) # we do not check for wlroots, as we provide it ourselves
|
||||||
|
+pkg_check_modules(deps REQUIRED IMPORTED_TARGET wayland-client wayland-cursor wayland-protocols cairo libdrm xkbcommon libinput pango pangocairo pixman-1 hyprlang>=0.3.2 libffi) # we do not check for wlroots, as we provide it ourselves
|
||||||
|
|
||||||
|
file(GLOB_RECURSE SRCFILES CONFIGURE_DEPENDS "src/*.cpp")
|
||||||
|
|
||||||
|
@@ -121,6 +121,7 @@ if(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG)
|
||||||
|
message(STATUS "Enabling ASan")
|
||||||
|
|
||||||
|
target_link_libraries(Hyprland asan)
|
||||||
|
+ target_link_libraries(Hyprland ${CMAKE_SOURCE_DIR}/libwayland-server.a)
|
||||||
|
target_compile_options(Hyprland PUBLIC -fsanitize=address)
|
||||||
|
endif()
|
||||||
|
|
23
scripts/waylandStatic.diff
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
diff --git a/src/meson.build b/src/meson.build
|
||||||
|
index 5d04334..6645eec 100644
|
||||||
|
--- a/src/meson.build
|
||||||
|
+++ b/src/meson.build
|
||||||
|
@@ -170,7 +170,7 @@ if get_option('libraries')
|
||||||
|
error('We probably need to bump the SONAME of libwayland-server and -client')
|
||||||
|
endif
|
||||||
|
|
||||||
|
- wayland_server = library(
|
||||||
|
+ wayland_server = static_library(
|
||||||
|
'wayland-server',
|
||||||
|
sources: [
|
||||||
|
wayland_server_protocol_core_h,
|
||||||
|
@@ -180,9 +180,6 @@ if get_option('libraries')
|
||||||
|
'wayland-shm.c',
|
||||||
|
'event-loop.c'
|
||||||
|
],
|
||||||
|
- # To avoid an unnecessary SONAME bump, wayland 1.x.y produces
|
||||||
|
- # libwayland-server.so.0.x.y.
|
||||||
|
- version: '.'.join(['0', wayland_version[1], wayland_version[2]]),
|
||||||
|
dependencies: [
|
||||||
|
epoll_dep,
|
||||||
|
ffi_dep,
|
|
@ -21,7 +21,7 @@
|
||||||
#include "debug/HyprDebugOverlay.hpp"
|
#include "debug/HyprDebugOverlay.hpp"
|
||||||
#include "debug/HyprNotificationOverlay.hpp"
|
#include "debug/HyprNotificationOverlay.hpp"
|
||||||
#include "helpers/Monitor.hpp"
|
#include "helpers/Monitor.hpp"
|
||||||
#include "helpers/Workspace.hpp"
|
#include "desktop/Workspace.hpp"
|
||||||
#include "Window.hpp"
|
#include "Window.hpp"
|
||||||
#include "render/Renderer.hpp"
|
#include "render/Renderer.hpp"
|
||||||
#include "render/OpenGL.hpp"
|
#include "render/OpenGL.hpp"
|
||||||
|
@ -93,9 +93,7 @@ class CCompositor {
|
||||||
std::vector<std::shared_ptr<CMonitor>> m_vMonitors;
|
std::vector<std::shared_ptr<CMonitor>> m_vMonitors;
|
||||||
std::vector<std::shared_ptr<CMonitor>> m_vRealMonitors; // for all monitors, even those turned off
|
std::vector<std::shared_ptr<CMonitor>> m_vRealMonitors; // for all monitors, even those turned off
|
||||||
std::vector<std::unique_ptr<CWindow>> m_vWindows;
|
std::vector<std::unique_ptr<CWindow>> m_vWindows;
|
||||||
std::vector<std::unique_ptr<SXDGPopup>> m_vXDGPopups;
|
|
||||||
std::vector<std::unique_ptr<CWorkspace>> m_vWorkspaces;
|
std::vector<std::unique_ptr<CWorkspace>> m_vWorkspaces;
|
||||||
std::vector<std::unique_ptr<SSubsurface>> m_vSubsurfaces;
|
|
||||||
std::vector<CWindow*> m_vWindowsFadingOut;
|
std::vector<CWindow*> m_vWindowsFadingOut;
|
||||||
std::vector<SLayerSurface*> m_vSurfacesFadingOut;
|
std::vector<SLayerSurface*> m_vSurfacesFadingOut;
|
||||||
|
|
||||||
|
@ -135,16 +133,14 @@ class CCompositor {
|
||||||
void focusSurface(wlr_surface*, CWindow* pWindowOwner = nullptr);
|
void focusSurface(wlr_surface*, CWindow* pWindowOwner = nullptr);
|
||||||
bool windowExists(CWindow*);
|
bool windowExists(CWindow*);
|
||||||
bool windowValidMapped(CWindow*);
|
bool windowValidMapped(CWindow*);
|
||||||
CWindow* vectorToWindowIdeal(const Vector2D&, CWindow* pIgnoreWindow = nullptr); // used only for finding a window to focus on, basically a "findFocusableWindow"
|
bool monitorExists(CMonitor*);
|
||||||
CWindow* vectorToWindowTiled(const Vector2D&);
|
CWindow* vectorToWindowUnified(const Vector2D&, uint8_t properties, CWindow* pIgnoreWindow = nullptr);
|
||||||
wlr_surface* vectorToLayerSurface(const Vector2D&, std::vector<std::unique_ptr<SLayerSurface>>*, Vector2D*, SLayerSurface**);
|
wlr_surface* vectorToLayerSurface(const Vector2D&, std::vector<std::unique_ptr<SLayerSurface>>*, Vector2D*, SLayerSurface**);
|
||||||
SIMEPopup* vectorToIMEPopup(const Vector2D& pos, std::list<SIMEPopup>& popups);
|
SIMEPopup* vectorToIMEPopup(const Vector2D& pos, std::list<SIMEPopup>& popups);
|
||||||
wlr_surface* vectorWindowToSurface(const Vector2D&, CWindow*, Vector2D& sl);
|
wlr_surface* vectorWindowToSurface(const Vector2D&, CWindow*, Vector2D& sl);
|
||||||
Vector2D vectorToSurfaceLocal(const Vector2D&, CWindow*, wlr_surface*);
|
Vector2D vectorToSurfaceLocal(const Vector2D&, CWindow*, wlr_surface*);
|
||||||
CWindow* windowFromCursor();
|
|
||||||
CWindow* windowFloatingFromCursor();
|
|
||||||
CMonitor* getMonitorFromOutput(wlr_output*);
|
CMonitor* getMonitorFromOutput(wlr_output*);
|
||||||
CWindow* getWindowForPopup(wlr_xdg_popup*);
|
CMonitor* getRealMonitorFromOutput(wlr_output*);
|
||||||
CWindow* getWindowFromSurface(wlr_surface*);
|
CWindow* getWindowFromSurface(wlr_surface*);
|
||||||
CWindow* getWindowFromHandle(uint32_t);
|
CWindow* getWindowFromHandle(uint32_t);
|
||||||
CWindow* getWindowFromZWLRHandle(wl_resource*);
|
CWindow* getWindowFromZWLRHandle(wl_resource*);
|
||||||
|
@ -172,11 +168,12 @@ class CCompositor {
|
||||||
bool isPointOnReservedArea(const Vector2D& point, const CMonitor* monitor = nullptr);
|
bool isPointOnReservedArea(const Vector2D& point, const CMonitor* monitor = nullptr);
|
||||||
CWindow* getConstraintWindow(SMouse*);
|
CWindow* getConstraintWindow(SMouse*);
|
||||||
CMonitor* getMonitorInDirection(const char&);
|
CMonitor* getMonitorInDirection(const char&);
|
||||||
|
CMonitor* getMonitorInDirection(CMonitor*, const char&);
|
||||||
void updateAllWindowsAnimatedDecorationValues();
|
void updateAllWindowsAnimatedDecorationValues();
|
||||||
void updateWorkspaceWindows(const int64_t& id);
|
void updateWorkspaceWindows(const int64_t& id);
|
||||||
void updateWindowAnimatedDecorationValues(CWindow*);
|
void updateWindowAnimatedDecorationValues(CWindow*);
|
||||||
int getNextAvailableMonitorID(std::string const& name);
|
int getNextAvailableMonitorID(std::string const& name);
|
||||||
void moveWorkspaceToMonitor(CWorkspace*, CMonitor*);
|
void moveWorkspaceToMonitor(CWorkspace*, CMonitor*, bool noWarpCursor = false);
|
||||||
void swapActiveWorkspaces(CMonitor*, CMonitor*);
|
void swapActiveWorkspaces(CMonitor*, CMonitor*);
|
||||||
CMonitor* getMonitorFromString(const std::string&);
|
CMonitor* getMonitorFromString(const std::string&);
|
||||||
bool workspaceIDOutOfBounds(const int64_t&);
|
bool workspaceIDOutOfBounds(const int64_t&);
|
||||||
|
@ -214,6 +211,7 @@ class CCompositor {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void initAllSignals();
|
void initAllSignals();
|
||||||
|
void removeAllSignals();
|
||||||
void setRandomSplash();
|
void setRandomSplash();
|
||||||
void initManagers(eManagersInitStage stage);
|
void initManagers(eManagersInitStage stage);
|
||||||
void prepareFallbackOutput();
|
void prepareFallbackOutput();
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "helpers/Vector2D.hpp"
|
#include "helpers/Vector2D.hpp"
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
enum eIcons {
|
enum eIcons {
|
||||||
ICON_WARNING = 0,
|
ICON_WARNING = 0,
|
||||||
|
@ -52,4 +53,20 @@ struct SWindowDecorationExtents {
|
||||||
bool operator==(const SWindowDecorationExtents& other) const {
|
bool operator==(const SWindowDecorationExtents& other) const {
|
||||||
return topLeft == other.topLeft && bottomRight == other.bottomRight;
|
return topLeft == other.topLeft && bottomRight == other.bottomRight;
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
void addExtents(const SWindowDecorationExtents& other) {
|
||||||
|
topLeft = topLeft.getComponentMax(other.topLeft);
|
||||||
|
bottomRight = bottomRight.getComponentMax(other.bottomRight);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
enum eHyprCtlOutputFormat {
|
||||||
|
FORMAT_NORMAL = 0,
|
||||||
|
FORMAT_JSON
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SHyprCtlCommand {
|
||||||
|
std::string name = "";
|
||||||
|
bool exact = true;
|
||||||
|
std::function<std::string(eHyprCtlOutputFormat, std::string)> fn;
|
||||||
|
};
|
||||||
|
|
179
src/Window.cpp
|
@ -5,14 +5,14 @@
|
||||||
#include "render/decorations/CHyprBorderDecoration.hpp"
|
#include "render/decorations/CHyprBorderDecoration.hpp"
|
||||||
|
|
||||||
CWindow::CWindow() {
|
CWindow::CWindow() {
|
||||||
m_vRealPosition.create(AVARTYPE_VECTOR, g_pConfigManager->getAnimationPropertyConfig("windowsIn"), (void*)this, AVARDAMAGE_ENTIRE);
|
m_vRealPosition.create(g_pConfigManager->getAnimationPropertyConfig("windowsIn"), (void*)this, AVARDAMAGE_ENTIRE);
|
||||||
m_vRealSize.create(AVARTYPE_VECTOR, g_pConfigManager->getAnimationPropertyConfig("windowsIn"), (void*)this, AVARDAMAGE_ENTIRE);
|
m_vRealSize.create(g_pConfigManager->getAnimationPropertyConfig("windowsIn"), (void*)this, AVARDAMAGE_ENTIRE);
|
||||||
m_fBorderFadeAnimationProgress.create(AVARTYPE_FLOAT, g_pConfigManager->getAnimationPropertyConfig("border"), (void*)this, AVARDAMAGE_BORDER);
|
m_fBorderFadeAnimationProgress.create(g_pConfigManager->getAnimationPropertyConfig("border"), (void*)this, AVARDAMAGE_BORDER);
|
||||||
m_fBorderAngleAnimationProgress.create(AVARTYPE_FLOAT, g_pConfigManager->getAnimationPropertyConfig("borderangle"), (void*)this, AVARDAMAGE_BORDER);
|
m_fBorderAngleAnimationProgress.create(g_pConfigManager->getAnimationPropertyConfig("borderangle"), (void*)this, AVARDAMAGE_BORDER);
|
||||||
m_fAlpha.create(AVARTYPE_FLOAT, g_pConfigManager->getAnimationPropertyConfig("fadeIn"), (void*)this, AVARDAMAGE_ENTIRE);
|
m_fAlpha.create(g_pConfigManager->getAnimationPropertyConfig("fadeIn"), (void*)this, AVARDAMAGE_ENTIRE);
|
||||||
m_fActiveInactiveAlpha.create(AVARTYPE_FLOAT, g_pConfigManager->getAnimationPropertyConfig("fadeSwitch"), (void*)this, AVARDAMAGE_ENTIRE);
|
m_fActiveInactiveAlpha.create(g_pConfigManager->getAnimationPropertyConfig("fadeSwitch"), (void*)this, AVARDAMAGE_ENTIRE);
|
||||||
m_cRealShadowColor.create(AVARTYPE_COLOR, g_pConfigManager->getAnimationPropertyConfig("fadeShadow"), (void*)this, AVARDAMAGE_SHADOW);
|
m_cRealShadowColor.create(g_pConfigManager->getAnimationPropertyConfig("fadeShadow"), (void*)this, AVARDAMAGE_SHADOW);
|
||||||
m_fDimPercent.create(AVARTYPE_FLOAT, g_pConfigManager->getAnimationPropertyConfig("fadeDim"), (void*)this, AVARDAMAGE_ENTIRE);
|
m_fDimPercent.create(g_pConfigManager->getAnimationPropertyConfig("fadeDim"), (void*)this, AVARDAMAGE_ENTIRE);
|
||||||
|
|
||||||
addWindowDeco(std::make_unique<CHyprDropShadowDecoration>(this));
|
addWindowDeco(std::make_unique<CHyprDropShadowDecoration>(this));
|
||||||
addWindowDeco(std::make_unique<CHyprBorderDecoration>(this));
|
addWindowDeco(std::make_unique<CHyprBorderDecoration>(this));
|
||||||
|
@ -39,8 +39,8 @@ SWindowDecorationExtents CWindow::getFullWindowExtents() {
|
||||||
|
|
||||||
if (m_sAdditionalConfigData.dimAround) {
|
if (m_sAdditionalConfigData.dimAround) {
|
||||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
|
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
|
||||||
return {{m_vRealPosition.vec().x - PMONITOR->vecPosition.x, m_vRealPosition.vec().y - PMONITOR->vecPosition.y},
|
return {{m_vRealPosition.value().x - PMONITOR->vecPosition.x, m_vRealPosition.value().y - PMONITOR->vecPosition.y},
|
||||||
{PMONITOR->vecSize.x - (m_vRealPosition.vec().x - PMONITOR->vecPosition.x), PMONITOR->vecSize.y - (m_vRealPosition.vec().y - PMONITOR->vecPosition.y)}};
|
{PMONITOR->vecSize.x - (m_vRealPosition.value().x - PMONITOR->vecPosition.x), PMONITOR->vecSize.y - (m_vRealPosition.value().y - PMONITOR->vecPosition.y)}};
|
||||||
}
|
}
|
||||||
|
|
||||||
SWindowDecorationExtents maxExtents = {{BORDERSIZE + 2, BORDERSIZE + 2}, {BORDERSIZE + 2, BORDERSIZE + 2}};
|
SWindowDecorationExtents maxExtents = {{BORDERSIZE + 2, BORDERSIZE + 2}, {BORDERSIZE + 2, BORDERSIZE + 2}};
|
||||||
|
@ -101,8 +101,8 @@ CBox CWindow::getFullWindowBoundingBox() {
|
||||||
|
|
||||||
auto maxExtents = getFullWindowExtents();
|
auto maxExtents = getFullWindowExtents();
|
||||||
|
|
||||||
CBox finalBox = {m_vRealPosition.vec().x - maxExtents.topLeft.x, m_vRealPosition.vec().y - maxExtents.topLeft.y,
|
CBox finalBox = {m_vRealPosition.value().x - maxExtents.topLeft.x, m_vRealPosition.value().y - maxExtents.topLeft.y,
|
||||||
m_vRealSize.vec().x + maxExtents.topLeft.x + maxExtents.bottomRight.x, m_vRealSize.vec().y + maxExtents.topLeft.y + maxExtents.bottomRight.y};
|
m_vRealSize.value().x + maxExtents.topLeft.x + maxExtents.bottomRight.x, m_vRealSize.value().y + maxExtents.topLeft.y + maxExtents.bottomRight.y};
|
||||||
|
|
||||||
return finalBox;
|
return finalBox;
|
||||||
}
|
}
|
||||||
|
@ -139,39 +139,29 @@ CBox CWindow::getWindowIdealBoundingBoxIgnoreReserved() {
|
||||||
return CBox{(int)POS.x, (int)POS.y, (int)SIZE.x, (int)SIZE.y};
|
return CBox{(int)POS.x, (int)POS.y, (int)SIZE.x, (int)SIZE.y};
|
||||||
}
|
}
|
||||||
|
|
||||||
CBox CWindow::getWindowInputBox() {
|
CBox CWindow::getWindowBoxUnified(uint64_t properties) {
|
||||||
const int BORDERSIZE = getRealBorderSize();
|
|
||||||
|
|
||||||
if (m_sAdditionalConfigData.dimAround) {
|
if (m_sAdditionalConfigData.dimAround) {
|
||||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
|
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
|
||||||
return {PMONITOR->vecPosition.x, PMONITOR->vecPosition.y, PMONITOR->vecSize.x, PMONITOR->vecSize.y};
|
return {PMONITOR->vecPosition.x, PMONITOR->vecPosition.y, PMONITOR->vecSize.x, PMONITOR->vecSize.y};
|
||||||
}
|
}
|
||||||
|
|
||||||
SWindowDecorationExtents maxExtents = {{BORDERSIZE + 2, BORDERSIZE + 2}, {BORDERSIZE + 2, BORDERSIZE + 2}};
|
SWindowDecorationExtents EXTENTS = {{0, 0}, {0, 0}};
|
||||||
|
if (properties & RESERVED_EXTENTS)
|
||||||
|
EXTENTS.addExtents(g_pDecorationPositioner->getWindowDecorationReserved(this));
|
||||||
|
if (properties & INPUT_EXTENTS)
|
||||||
|
EXTENTS.addExtents(g_pDecorationPositioner->getWindowDecorationExtents(this, true));
|
||||||
|
if (properties & FULL_EXTENTS)
|
||||||
|
EXTENTS.addExtents(g_pDecorationPositioner->getWindowDecorationExtents(this, false));
|
||||||
|
|
||||||
const auto EXTENTS = g_pDecorationPositioner->getWindowDecorationExtents(this, true);
|
CBox box = {m_vRealPosition.value().x, m_vRealPosition.value().y, m_vRealSize.value().x, m_vRealSize.value().y};
|
||||||
|
box.addExtents(EXTENTS);
|
||||||
|
|
||||||
if (EXTENTS.topLeft.x > maxExtents.topLeft.x)
|
return box;
|
||||||
maxExtents.topLeft.x = EXTENTS.topLeft.x;
|
|
||||||
|
|
||||||
if (EXTENTS.topLeft.y > maxExtents.topLeft.y)
|
|
||||||
maxExtents.topLeft.y = EXTENTS.topLeft.y;
|
|
||||||
|
|
||||||
if (EXTENTS.bottomRight.x > maxExtents.bottomRight.x)
|
|
||||||
maxExtents.bottomRight.x = EXTENTS.bottomRight.x;
|
|
||||||
|
|
||||||
if (EXTENTS.bottomRight.y > maxExtents.bottomRight.y)
|
|
||||||
maxExtents.bottomRight.y = EXTENTS.bottomRight.y;
|
|
||||||
|
|
||||||
// Add extents to the real base BB and return
|
|
||||||
CBox finalBox = {m_vRealPosition.vec().x - maxExtents.topLeft.x, m_vRealPosition.vec().y - maxExtents.topLeft.y,
|
|
||||||
m_vRealSize.vec().x + maxExtents.topLeft.x + maxExtents.bottomRight.x, m_vRealSize.vec().y + maxExtents.topLeft.y + maxExtents.bottomRight.y};
|
|
||||||
|
|
||||||
return finalBox;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CBox CWindow::getWindowMainSurfaceBox() {
|
CBox CWindow::getWindowMainSurfaceBox() {
|
||||||
return {m_vRealPosition.vec().x, m_vRealPosition.vec().y, m_vRealSize.vec().x, m_vRealSize.vec().y};
|
return {m_vRealPosition.value().x, m_vRealPosition.value().y, m_vRealSize.value().x, m_vRealSize.value().y};
|
||||||
}
|
}
|
||||||
|
|
||||||
SWindowDecorationExtents CWindow::getFullWindowReservedArea() {
|
SWindowDecorationExtents CWindow::getFullWindowReservedArea() {
|
||||||
|
@ -318,7 +308,7 @@ void CWindow::destroyToplevelHandle() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void CWindow::updateToplevel() {
|
void CWindow::updateToplevel() {
|
||||||
updateSurfaceOutputs();
|
updateSurfaceScaleTransformDetails();
|
||||||
|
|
||||||
if (!m_phForeignToplevel)
|
if (!m_phForeignToplevel)
|
||||||
return;
|
return;
|
||||||
|
@ -345,8 +335,8 @@ void sendLeaveIter(wlr_surface* pSurface, int x, int y, void* data) {
|
||||||
wlr_surface_send_leave(pSurface, OUTPUT);
|
wlr_surface_send_leave(pSurface, OUTPUT);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CWindow::updateSurfaceOutputs() {
|
void CWindow::updateSurfaceScaleTransformDetails() {
|
||||||
if (m_iLastSurfaceMonitorID == m_iMonitorID || !m_bIsMapped || m_bHidden)
|
if (!m_bIsMapped || m_bHidden)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const auto PLASTMONITOR = g_pCompositor->getMonitorFromID(m_iLastSurfaceMonitorID);
|
const auto PLASTMONITOR = g_pCompositor->getMonitorFromID(m_iLastSurfaceMonitorID);
|
||||||
|
@ -355,16 +345,23 @@ void CWindow::updateSurfaceOutputs() {
|
||||||
|
|
||||||
const auto PNEWMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
|
const auto PNEWMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
|
||||||
|
|
||||||
if (PLASTMONITOR && PLASTMONITOR->m_bEnabled)
|
if (PNEWMONITOR != PLASTMONITOR) {
|
||||||
wlr_surface_for_each_surface(m_pWLSurface.wlr(), sendLeaveIter, PLASTMONITOR->output);
|
if (PLASTMONITOR && PLASTMONITOR->m_bEnabled)
|
||||||
|
wlr_surface_for_each_surface(m_pWLSurface.wlr(), sendLeaveIter, PLASTMONITOR->output);
|
||||||
|
|
||||||
wlr_surface_for_each_surface(m_pWLSurface.wlr(), sendEnterIter, PNEWMONITOR->output);
|
wlr_surface_for_each_surface(m_pWLSurface.wlr(), sendEnterIter, PNEWMONITOR->output);
|
||||||
|
}
|
||||||
|
|
||||||
wlr_surface_for_each_surface(
|
wlr_surface_for_each_surface(
|
||||||
m_pWLSurface.wlr(),
|
m_pWLSurface.wlr(),
|
||||||
[](wlr_surface* surf, int x, int y, void* data) {
|
[](wlr_surface* surf, int x, int y, void* data) {
|
||||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(((CWindow*)data)->m_iMonitorID);
|
const auto PMONITOR = g_pCompositor->getMonitorFromID(((CWindow*)data)->m_iMonitorID);
|
||||||
g_pCompositor->setPreferredScaleForSurface(surf, PMONITOR ? PMONITOR->scale : 1.f);
|
|
||||||
|
const auto PSURFACE = CWLSurface::surfaceFromWlr(surf);
|
||||||
|
if (PSURFACE && PSURFACE->m_fLastScale == PMONITOR->scale)
|
||||||
|
return;
|
||||||
|
|
||||||
|
g_pCompositor->setPreferredScaleForSurface(surf, PMONITOR->scale);
|
||||||
g_pCompositor->setPreferredTransformForSurface(surf, PMONITOR->transform);
|
g_pCompositor->setPreferredTransformForSurface(surf, PMONITOR->transform);
|
||||||
},
|
},
|
||||||
this);
|
this);
|
||||||
|
@ -374,7 +371,7 @@ void CWindow::moveToWorkspace(int workspaceID) {
|
||||||
if (m_iWorkspaceID == workspaceID)
|
if (m_iWorkspaceID == workspaceID)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
static auto* const PCLOSEONLASTSPECIAL = &g_pConfigManager->getConfigValuePtr("misc:close_special_on_empty")->intValue;
|
static auto* const PCLOSEONLASTSPECIAL = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("misc:close_special_on_empty");
|
||||||
|
|
||||||
const int OLDWORKSPACE = m_iWorkspaceID;
|
const int OLDWORKSPACE = m_iWorkspaceID;
|
||||||
|
|
||||||
|
@ -395,9 +392,9 @@ void CWindow::moveToWorkspace(int workspaceID) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// update xwayland coords
|
// update xwayland coords
|
||||||
g_pXWaylandManager->setWindowSize(this, m_vRealSize.vec());
|
g_pXWaylandManager->setWindowSize(this, m_vRealSize.value());
|
||||||
|
|
||||||
if (g_pCompositor->isWorkspaceSpecial(OLDWORKSPACE) && g_pCompositor->getWindowsOnWorkspace(OLDWORKSPACE) == 0 && *PCLOSEONLASTSPECIAL) {
|
if (g_pCompositor->isWorkspaceSpecial(OLDWORKSPACE) && g_pCompositor->getWindowsOnWorkspace(OLDWORKSPACE) == 0 && **PCLOSEONLASTSPECIAL) {
|
||||||
const auto PWS = g_pCompositor->getWorkspaceByID(OLDWORKSPACE);
|
const auto PWS = g_pCompositor->getWorkspaceByID(OLDWORKSPACE);
|
||||||
|
|
||||||
if (PWS) {
|
if (PWS) {
|
||||||
|
@ -436,11 +433,11 @@ void CWindow::removeDecorationByType(eDecorationType type) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void unregisterVar(void* ptr) {
|
void unregisterVar(void* ptr) {
|
||||||
((CAnimatedVariable*)ptr)->unregister();
|
((CBaseAnimatedVariable*)ptr)->unregister();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CWindow::onUnmap() {
|
void CWindow::onUnmap() {
|
||||||
static auto* const PCLOSEONLASTSPECIAL = &g_pConfigManager->getConfigValuePtr("misc:close_special_on_empty")->intValue;
|
static auto* const PCLOSEONLASTSPECIAL = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("misc:close_special_on_empty");
|
||||||
|
|
||||||
if (g_pCompositor->m_pLastWindow == this)
|
if (g_pCompositor->m_pLastWindow == this)
|
||||||
g_pCompositor->m_pLastWindow = nullptr;
|
g_pCompositor->m_pLastWindow = nullptr;
|
||||||
|
@ -462,7 +459,7 @@ void CWindow::onUnmap() {
|
||||||
|
|
||||||
hyprListener_unmapWindow.removeCallback();
|
hyprListener_unmapWindow.removeCallback();
|
||||||
|
|
||||||
if (*PCLOSEONLASTSPECIAL && g_pCompositor->getWindowsOnWorkspace(m_iWorkspaceID) == 0 && g_pCompositor->isWorkspaceSpecial(m_iWorkspaceID)) {
|
if (**PCLOSEONLASTSPECIAL && g_pCompositor->getWindowsOnWorkspace(m_iWorkspaceID) == 0 && g_pCompositor->isWorkspaceSpecial(m_iWorkspaceID)) {
|
||||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
|
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
|
||||||
if (PMONITOR && PMONITOR->specialWorkspaceID == m_iWorkspaceID)
|
if (PMONITOR && PMONITOR->specialWorkspaceID == m_iWorkspaceID)
|
||||||
PMONITOR->setSpecialWorkspace(nullptr);
|
PMONITOR->setSpecialWorkspace(nullptr);
|
||||||
|
@ -474,12 +471,17 @@ void CWindow::onUnmap() {
|
||||||
PMONITOR->solitaryClient = nullptr;
|
PMONITOR->solitaryClient = nullptr;
|
||||||
|
|
||||||
g_pCompositor->updateWorkspaceWindows(m_iWorkspaceID);
|
g_pCompositor->updateWorkspaceWindows(m_iWorkspaceID);
|
||||||
|
|
||||||
|
if (m_bIsX11)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_pSubsurfaceHead.reset();
|
||||||
|
m_pPopupHead.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CWindow::onMap() {
|
void CWindow::onMap() {
|
||||||
|
|
||||||
m_pWLSurface.assign(g_pXWaylandManager->getWindowSurface(this));
|
m_pWLSurface.assign(g_pXWaylandManager->getWindowSurface(this), this);
|
||||||
m_pWLSurface.m_pOwner = this;
|
|
||||||
|
|
||||||
// JIC, reset the callbacks. If any are set, we'll make sure they are cleared so we don't accidentally unset them. (In case a window got remapped)
|
// JIC, reset the callbacks. If any are set, we'll make sure they are cleared so we don't accidentally unset them. (In case a window got remapped)
|
||||||
m_vRealPosition.resetAllCallbacks();
|
m_vRealPosition.resetAllCallbacks();
|
||||||
|
@ -511,10 +513,24 @@ void CWindow::onMap() {
|
||||||
"CWindow");
|
"CWindow");
|
||||||
|
|
||||||
m_vReportedSize = m_vPendingReportedSize;
|
m_vReportedSize = m_vPendingReportedSize;
|
||||||
|
|
||||||
|
for (const auto& ctrl : g_pHyprRenderer->m_vTearingControllers) {
|
||||||
|
if (ctrl->pWlrHint->surface != m_pWLSurface.wlr())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
m_bTearingHint = ctrl->pWlrHint->current;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_bIsX11)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_pSubsurfaceHead = std::make_unique<CSubsurface>(this);
|
||||||
|
m_pPopupHead = std::make_unique<CPopup>(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CWindow::onBorderAngleAnimEnd(void* ptr) {
|
void CWindow::onBorderAngleAnimEnd(void* ptr) {
|
||||||
const auto PANIMVAR = (CAnimatedVariable*)ptr;
|
const auto PANIMVAR = (CAnimatedVariable<float>*)ptr;
|
||||||
|
|
||||||
const std::string STYLE = PANIMVAR->getConfig()->pValues->internalStyle;
|
const std::string STYLE = PANIMVAR->getConfig()->pValues->internalStyle;
|
||||||
|
|
||||||
|
@ -625,23 +641,22 @@ void CWindow::applyDynamicRule(const SWindowRule& r) {
|
||||||
if (active && token.contains("deg")) {
|
if (active && token.contains("deg")) {
|
||||||
activeBorderGradient.m_fAngle = std::stoi(token.substr(0, token.size() - 3)) * (PI / 180.0);
|
activeBorderGradient.m_fAngle = std::stoi(token.substr(0, token.size() - 3)) * (PI / 180.0);
|
||||||
active = false;
|
active = false;
|
||||||
} else if (token.contains("deg")) {
|
} else if (token.contains("deg"))
|
||||||
inactiveBorderGradient.m_fAngle = std::stoi(token.substr(0, token.size() - 3)) * (PI / 180.0);
|
inactiveBorderGradient.m_fAngle = std::stoi(token.substr(0, token.size() - 3)) * (PI / 180.0);
|
||||||
} else if (active) {
|
else if (active)
|
||||||
activeBorderGradient.m_vColors.push_back(configStringToInt(token));
|
activeBorderGradient.m_vColors.push_back(configStringToInt(token));
|
||||||
} else {
|
else
|
||||||
inactiveBorderGradient.m_vColors.push_back(configStringToInt(token));
|
inactiveBorderGradient.m_vColors.push_back(configStringToInt(token));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Includes sanity checks for the number of colors in each gradient
|
// Includes sanity checks for the number of colors in each gradient
|
||||||
if (activeBorderGradient.m_vColors.size() > 10 || inactiveBorderGradient.m_vColors.size() > 10) {
|
if (activeBorderGradient.m_vColors.size() > 10 || inactiveBorderGradient.m_vColors.size() > 10)
|
||||||
Debug::log(WARN, "Bordercolor rule \"{}\" has more than 10 colors in one gradient, ignoring", r.szRule);
|
Debug::log(WARN, "Bordercolor rule \"{}\" has more than 10 colors in one gradient, ignoring", r.szRule);
|
||||||
} else if (activeBorderGradient.m_vColors.empty()) {
|
else if (activeBorderGradient.m_vColors.empty())
|
||||||
Debug::log(WARN, "Bordercolor rule \"{}\" has no colors, ignoring", r.szRule);
|
Debug::log(WARN, "Bordercolor rule \"{}\" has no colors, ignoring", r.szRule);
|
||||||
} else if (inactiveBorderGradient.m_vColors.empty()) {
|
else if (inactiveBorderGradient.m_vColors.empty())
|
||||||
m_sSpecialRenderData.activeBorderColor = activeBorderGradient;
|
m_sSpecialRenderData.activeBorderColor = activeBorderGradient;
|
||||||
} else {
|
else {
|
||||||
m_sSpecialRenderData.activeBorderColor = activeBorderGradient;
|
m_sSpecialRenderData.activeBorderColor = activeBorderGradient;
|
||||||
m_sSpecialRenderData.inactiveBorderColor = inactiveBorderGradient;
|
m_sSpecialRenderData.inactiveBorderColor = inactiveBorderGradient;
|
||||||
}
|
}
|
||||||
|
@ -712,10 +727,10 @@ bool CWindow::isInCurvedCorner(double x, double y) {
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// (x0, y0), (x0, y1), ... are the center point of rounding at each corner
|
// (x0, y0), (x0, y1), ... are the center point of rounding at each corner
|
||||||
double x0 = m_vRealPosition.vec().x + ROUNDING;
|
double x0 = m_vRealPosition.value().x + ROUNDING;
|
||||||
double y0 = m_vRealPosition.vec().y + ROUNDING;
|
double y0 = m_vRealPosition.value().y + ROUNDING;
|
||||||
double x1 = m_vRealPosition.vec().x + m_vRealSize.vec().x - ROUNDING;
|
double x1 = m_vRealPosition.value().x + m_vRealSize.value().x - ROUNDING;
|
||||||
double y1 = m_vRealPosition.vec().y + m_vRealSize.vec().y - ROUNDING;
|
double y1 = m_vRealPosition.value().y + m_vRealSize.value().y - ROUNDING;
|
||||||
|
|
||||||
if (x < x0 && y < y0) {
|
if (x < x0 && y < y0) {
|
||||||
return Vector2D{x0, y0}.distance(Vector2D{x, y}) > (double)ROUNDING;
|
return Vector2D{x0, y0}.distance(Vector2D{x, y}) > (double)ROUNDING;
|
||||||
|
@ -748,7 +763,7 @@ bool CWindow::hasPopupAt(const Vector2D& pos) {
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
wlr_surface* resultSurf = nullptr;
|
wlr_surface* resultSurf = nullptr;
|
||||||
Vector2D origin = m_vRealPosition.vec();
|
Vector2D origin = m_vRealPosition.value();
|
||||||
SExtensionFindingData data = {origin, pos, &resultSurf};
|
SExtensionFindingData data = {origin, pos, &resultSurf};
|
||||||
wlr_xdg_surface_for_each_popup_surface(m_uSurface.xdg, findExtensionForVector2D, &data);
|
wlr_xdg_surface_for_each_popup_surface(m_uSurface.xdg, findExtensionForVector2D, &data);
|
||||||
|
|
||||||
|
@ -887,8 +902,8 @@ void CWindow::setGroupCurrent(CWindow* pWindow) {
|
||||||
const bool FULLSCREEN = PCURRENT->m_bIsFullscreen;
|
const bool FULLSCREEN = PCURRENT->m_bIsFullscreen;
|
||||||
const auto WORKSPACE = g_pCompositor->getWorkspaceByID(PCURRENT->m_iWorkspaceID);
|
const auto WORKSPACE = g_pCompositor->getWorkspaceByID(PCURRENT->m_iWorkspaceID);
|
||||||
|
|
||||||
const auto PWINDOWSIZE = PCURRENT->m_vRealSize.goalv();
|
const auto PWINDOWSIZE = PCURRENT->m_vRealSize.goal();
|
||||||
const auto PWINDOWPOS = PCURRENT->m_vRealPosition.goalv();
|
const auto PWINDOWPOS = PCURRENT->m_vRealPosition.goal();
|
||||||
|
|
||||||
const auto CURRENTISFOCUS = PCURRENT == g_pCompositor->m_pLastWindow;
|
const auto CURRENTISFOCUS = PCURRENT == g_pCompositor->m_pLastWindow;
|
||||||
|
|
||||||
|
@ -982,19 +997,19 @@ void CWindow::updateGroupOutputs() {
|
||||||
curr->m_iMonitorID = m_iMonitorID;
|
curr->m_iMonitorID = m_iMonitorID;
|
||||||
curr->moveToWorkspace(m_iWorkspaceID);
|
curr->moveToWorkspace(m_iWorkspaceID);
|
||||||
|
|
||||||
curr->m_vRealPosition = m_vRealPosition.goalv();
|
curr->m_vRealPosition = m_vRealPosition.goal();
|
||||||
curr->m_vRealSize = m_vRealSize.goalv();
|
curr->m_vRealSize = m_vRealSize.goal();
|
||||||
|
|
||||||
curr = curr->m_sGroupData.pNextWindow;
|
curr = curr->m_sGroupData.pNextWindow;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector2D CWindow::middle() {
|
Vector2D CWindow::middle() {
|
||||||
return m_vRealPosition.goalv() + m_vRealSize.goalv() / 2.f;
|
return m_vRealPosition.goal() + m_vRealSize.goal() / 2.f;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CWindow::opaque() {
|
bool CWindow::opaque() {
|
||||||
if (m_fAlpha.fl() != 1.f || m_fActiveInactiveAlpha.fl() != 1.f)
|
if (m_fAlpha.value() != 1.f || m_fActiveInactiveAlpha.value() != 1.f)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(m_iWorkspaceID);
|
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(m_iWorkspaceID);
|
||||||
|
@ -1002,7 +1017,7 @@ bool CWindow::opaque() {
|
||||||
if (m_pWLSurface.small() && !m_pWLSurface.m_bFillIgnoreSmall)
|
if (m_pWLSurface.small() && !m_pWLSurface.m_bFillIgnoreSmall)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (PWORKSPACE->m_fAlpha.fl() != 1.f)
|
if (PWORKSPACE->m_fAlpha.value() != 1.f)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (m_bIsX11)
|
if (m_bIsX11)
|
||||||
|
@ -1019,19 +1034,21 @@ bool CWindow::opaque() {
|
||||||
}
|
}
|
||||||
|
|
||||||
float CWindow::rounding() {
|
float CWindow::rounding() {
|
||||||
static auto* const PROUNDING = &g_pConfigManager->getConfigValuePtr("decoration:rounding")->intValue;
|
static auto* const PROUNDING = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("decoration:rounding");
|
||||||
|
|
||||||
float rounding = m_sAdditionalConfigData.rounding.toUnderlying() == -1 ? *PROUNDING : m_sAdditionalConfigData.rounding.toUnderlying();
|
float rounding = m_sAdditionalConfigData.rounding.toUnderlying() == -1 ? **PROUNDING : m_sAdditionalConfigData.rounding.toUnderlying();
|
||||||
|
|
||||||
return m_sSpecialRenderData.rounding ? rounding : 0;
|
return m_sSpecialRenderData.rounding ? rounding : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CWindow::updateSpecialRenderData() {
|
void CWindow::updateSpecialRenderData() {
|
||||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(m_iWorkspaceID);
|
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(m_iWorkspaceID);
|
||||||
const auto WORKSPACERULE = PWORKSPACE ? g_pConfigManager->getWorkspaceRuleFor(PWORKSPACE) : SWorkspaceRule{};
|
const auto WORKSPACERULE = PWORKSPACE ? g_pConfigManager->getWorkspaceRuleFor(PWORKSPACE) : SWorkspaceRule{};
|
||||||
bool border = true;
|
bool border = true;
|
||||||
|
|
||||||
if (m_bIsFloating && g_pConfigManager->getConfigValuePtr("general:no_border_on_floating")->intValue == 1)
|
static auto* const* PNOBORDERONFLOATING = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("general:no_border_on_floating");
|
||||||
|
|
||||||
|
if (m_bIsFloating && **PNOBORDERONFLOATING == 1)
|
||||||
border = false;
|
border = false;
|
||||||
|
|
||||||
m_sSpecialRenderData.border = WORKSPACERULE.border.value_or(border);
|
m_sSpecialRenderData.border = WORKSPACERULE.border.value_or(border);
|
||||||
|
@ -1051,16 +1068,18 @@ int CWindow::getRealBorderSize() {
|
||||||
if (m_sSpecialRenderData.borderSize.toUnderlying() != -1)
|
if (m_sSpecialRenderData.borderSize.toUnderlying() != -1)
|
||||||
return m_sSpecialRenderData.borderSize.toUnderlying();
|
return m_sSpecialRenderData.borderSize.toUnderlying();
|
||||||
|
|
||||||
return g_pConfigManager->getConfigValuePtr("general:border_size")->intValue;
|
static auto* const* PBORDERSIZE = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("general:border_size");
|
||||||
|
|
||||||
|
return **PBORDERSIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CWindow::canBeTorn() {
|
bool CWindow::canBeTorn() {
|
||||||
return (m_sAdditionalConfigData.forceTearing.toUnderlying() || m_bTearingHint) && g_pHyprRenderer->m_bTearingEnvSatisfied;
|
return (m_sAdditionalConfigData.forceTearing.toUnderlying() || m_bTearingHint);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CWindow::shouldSendFullscreenState() {
|
bool CWindow::shouldSendFullscreenState() {
|
||||||
const auto MODE = g_pCompositor->getWorkspaceByID(m_iWorkspaceID)->m_efFullscreenMode;
|
const auto MODE = g_pCompositor->getWorkspaceByID(m_iWorkspaceID)->m_efFullscreenMode;
|
||||||
return m_bFakeFullscreenState || (m_bIsFullscreen && (MODE == FULLSCREEN_FULL));
|
return m_bDontSendFullscreen ? false : (m_bFakeFullscreenState || (m_bIsFullscreen && (MODE == FULLSCREEN_FULL)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void CWindow::setSuspended(bool suspend) {
|
void CWindow::setSuspended(bool suspend) {
|
||||||
|
|
|
@ -1,13 +1,14 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "defines.hpp"
|
#include "defines.hpp"
|
||||||
#include "helpers/SubsurfaceTree.hpp"
|
#include "desktop/Subsurface.hpp"
|
||||||
#include "helpers/AnimatedVariable.hpp"
|
#include "helpers/AnimatedVariable.hpp"
|
||||||
#include "render/decorations/IHyprWindowDecoration.hpp"
|
#include "render/decorations/IHyprWindowDecoration.hpp"
|
||||||
#include <deque>
|
#include <deque>
|
||||||
#include "config/ConfigDataValues.hpp"
|
#include "config/ConfigDataValues.hpp"
|
||||||
#include "helpers/Vector2D.hpp"
|
#include "helpers/Vector2D.hpp"
|
||||||
#include "helpers/WLSurface.hpp"
|
#include "desktop/WLSurface.hpp"
|
||||||
|
#include "desktop/Popup.hpp"
|
||||||
#include "macros.hpp"
|
#include "macros.hpp"
|
||||||
#include "managers/XWaylandManager.hpp"
|
#include "managers/XWaylandManager.hpp"
|
||||||
|
|
||||||
|
@ -30,6 +31,24 @@ enum eGroupRules {
|
||||||
GROUP_OVERRIDE = 1 << 6, // Override other rules
|
GROUP_OVERRIDE = 1 << 6, // Override other rules
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum eGetWindowProperties {
|
||||||
|
WINDOW_ONLY = 0,
|
||||||
|
RESERVED_EXTENTS = 1 << 0,
|
||||||
|
INPUT_EXTENTS = 1 << 1,
|
||||||
|
FULL_EXTENTS = 1 << 2,
|
||||||
|
FLOATING_ONLY = 1 << 3,
|
||||||
|
ALLOW_FLOATING = 1 << 4,
|
||||||
|
USE_PROP_TILED = 1 << 5,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum eSuppressEvents {
|
||||||
|
SUPPRESS_NONE = 0,
|
||||||
|
SUPPRESS_FULLSCREEN = 1 << 0,
|
||||||
|
SUPPRESS_MAXIMIZE = 1 << 1,
|
||||||
|
SUPPRESS_ACTIVATE = 1 << 2,
|
||||||
|
SUPPRESS_ACTIVATE_FOCUSONLY = 1 << 3,
|
||||||
|
};
|
||||||
|
|
||||||
class IWindowTransformer;
|
class IWindowTransformer;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
@ -133,6 +152,7 @@ struct SWindowAdditionalConfigData {
|
||||||
CWindowOverridableVar<bool> forceNoBorder = false;
|
CWindowOverridableVar<bool> forceNoBorder = false;
|
||||||
CWindowOverridableVar<bool> forceNoShadow = false;
|
CWindowOverridableVar<bool> forceNoShadow = false;
|
||||||
CWindowOverridableVar<bool> forceNoDim = false;
|
CWindowOverridableVar<bool> forceNoDim = false;
|
||||||
|
CWindowOverridableVar<bool> noFocus = false;
|
||||||
CWindowOverridableVar<bool> windowDanceCompat = false;
|
CWindowOverridableVar<bool> windowDanceCompat = false;
|
||||||
CWindowOverridableVar<bool> noMaxSize = false;
|
CWindowOverridableVar<bool> noMaxSize = false;
|
||||||
CWindowOverridableVar<bool> dimAround = false;
|
CWindowOverridableVar<bool> dimAround = false;
|
||||||
|
@ -174,7 +194,6 @@ class CWindow {
|
||||||
DYNLISTENER(setTitleWindow);
|
DYNLISTENER(setTitleWindow);
|
||||||
DYNLISTENER(setGeometryX11U);
|
DYNLISTENER(setGeometryX11U);
|
||||||
DYNLISTENER(fullscreenWindow);
|
DYNLISTENER(fullscreenWindow);
|
||||||
DYNLISTENER(newPopupXDG);
|
|
||||||
DYNLISTENER(requestMove);
|
DYNLISTENER(requestMove);
|
||||||
DYNLISTENER(requestMinimize);
|
DYNLISTENER(requestMinimize);
|
||||||
DYNLISTENER(requestMaximize);
|
DYNLISTENER(requestMaximize);
|
||||||
|
@ -190,8 +209,7 @@ class CWindow {
|
||||||
DYNLISTENER(ackConfigure);
|
DYNLISTENER(ackConfigure);
|
||||||
// DYNLISTENER(newSubsurfaceWindow);
|
// DYNLISTENER(newSubsurfaceWindow);
|
||||||
|
|
||||||
CWLSurface m_pWLSurface;
|
CWLSurface m_pWLSurface;
|
||||||
std::list<CWLSurface> m_lPopupSurfaces;
|
|
||||||
|
|
||||||
union {
|
union {
|
||||||
wlr_xdg_surface* xdg;
|
wlr_xdg_surface* xdg;
|
||||||
|
@ -203,8 +221,8 @@ class CWindow {
|
||||||
Vector2D m_vSize = Vector2D(0, 0);
|
Vector2D m_vSize = Vector2D(0, 0);
|
||||||
|
|
||||||
// this is the real position and size used to draw the thing
|
// this is the real position and size used to draw the thing
|
||||||
CAnimatedVariable m_vRealPosition;
|
CAnimatedVariable<Vector2D> m_vRealPosition;
|
||||||
CAnimatedVariable m_vRealSize;
|
CAnimatedVariable<Vector2D> m_vRealSize;
|
||||||
|
|
||||||
// for not spamming the protocols
|
// for not spamming the protocols
|
||||||
Vector2D m_vReportedPosition;
|
Vector2D m_vReportedPosition;
|
||||||
|
@ -221,16 +239,17 @@ class CWindow {
|
||||||
bool m_bIsPseudotiled = false;
|
bool m_bIsPseudotiled = false;
|
||||||
Vector2D m_vPseudoSize = Vector2D(0, 0);
|
Vector2D m_vPseudoSize = Vector2D(0, 0);
|
||||||
|
|
||||||
bool m_bFirstMap = false; // for layouts
|
bool m_bFirstMap = false; // for layouts
|
||||||
bool m_bIsFloating = false;
|
bool m_bIsFloating = false;
|
||||||
bool m_bDraggingTiled = false; // for dragging around tiled windows
|
bool m_bDraggingTiled = false; // for dragging around tiled windows
|
||||||
bool m_bIsFullscreen = false;
|
bool m_bIsFullscreen = false;
|
||||||
bool m_bWasMaximized = false;
|
bool m_bDontSendFullscreen = false;
|
||||||
uint64_t m_iMonitorID = -1;
|
bool m_bWasMaximized = false;
|
||||||
std::string m_szTitle = "";
|
uint64_t m_iMonitorID = -1;
|
||||||
std::string m_szInitialTitle = "";
|
std::string m_szTitle = "";
|
||||||
std::string m_szInitialClass = "";
|
std::string m_szInitialTitle = "";
|
||||||
int m_iWorkspaceID = -1;
|
std::string m_szInitialClass = "";
|
||||||
|
int m_iWorkspaceID = -1;
|
||||||
|
|
||||||
bool m_bIsMapped = false;
|
bool m_bIsMapped = false;
|
||||||
|
|
||||||
|
@ -250,24 +269,26 @@ class CWindow {
|
||||||
//
|
//
|
||||||
|
|
||||||
// For nofocus
|
// For nofocus
|
||||||
bool m_bNoFocus = false;
|
|
||||||
bool m_bNoInitialFocus = false;
|
bool m_bNoInitialFocus = false;
|
||||||
|
|
||||||
// Fullscreen and Maximize
|
// Fullscreen and Maximize
|
||||||
bool m_bWantsInitialFullscreen = false;
|
bool m_bWantsInitialFullscreen = false;
|
||||||
bool m_bNoFullscreenRequest = false;
|
|
||||||
bool m_bNoMaximizeRequest = false;
|
|
||||||
|
|
||||||
SSurfaceTreeNode* m_pSurfaceTree = nullptr;
|
// bitfield eSuppressEvents
|
||||||
|
uint64_t m_eSuppressedEvents = SUPPRESS_NONE;
|
||||||
|
|
||||||
|
// desktop components
|
||||||
|
std::unique_ptr<CSubsurface> m_pSubsurfaceHead;
|
||||||
|
std::unique_ptr<CPopup> m_pPopupHead;
|
||||||
|
|
||||||
// Animated border
|
// Animated border
|
||||||
CGradientValueData m_cRealBorderColor = {0};
|
CGradientValueData m_cRealBorderColor = {0};
|
||||||
CGradientValueData m_cRealBorderColorPrevious = {0};
|
CGradientValueData m_cRealBorderColorPrevious = {0};
|
||||||
CAnimatedVariable m_fBorderFadeAnimationProgress;
|
CAnimatedVariable<float> m_fBorderFadeAnimationProgress;
|
||||||
CAnimatedVariable m_fBorderAngleAnimationProgress;
|
CAnimatedVariable<float> m_fBorderAngleAnimationProgress;
|
||||||
|
|
||||||
// Fade in-out
|
// Fade in-out
|
||||||
CAnimatedVariable m_fAlpha;
|
CAnimatedVariable<float> m_fAlpha;
|
||||||
bool m_bFadingOut = false;
|
bool m_bFadingOut = false;
|
||||||
bool m_bReadyToDelete = false;
|
bool m_bReadyToDelete = false;
|
||||||
Vector2D m_vOriginalClosedPos; // these will be used for calculations later on in
|
Vector2D m_vOriginalClosedPos; // these will be used for calculations later on in
|
||||||
|
@ -301,13 +322,13 @@ class CWindow {
|
||||||
std::vector<std::unique_ptr<IWindowTransformer>> m_vTransformers;
|
std::vector<std::unique_ptr<IWindowTransformer>> m_vTransformers;
|
||||||
|
|
||||||
// for alpha
|
// for alpha
|
||||||
CAnimatedVariable m_fActiveInactiveAlpha;
|
CAnimatedVariable<float> m_fActiveInactiveAlpha;
|
||||||
|
|
||||||
// animated shadow color
|
// animated shadow color
|
||||||
CAnimatedVariable m_cRealShadowColor;
|
CAnimatedVariable<CColor> m_cRealShadowColor;
|
||||||
|
|
||||||
// animated tint
|
// animated tint
|
||||||
CAnimatedVariable m_fDimPercent;
|
CAnimatedVariable<float> m_fDimPercent;
|
||||||
|
|
||||||
// swallowing
|
// swallowing
|
||||||
CWindow* m_pSwallowed = nullptr;
|
CWindow* m_pSwallowed = nullptr;
|
||||||
|
@ -342,7 +363,7 @@ class CWindow {
|
||||||
// methods
|
// methods
|
||||||
CBox getFullWindowBoundingBox();
|
CBox getFullWindowBoundingBox();
|
||||||
SWindowDecorationExtents getFullWindowExtents();
|
SWindowDecorationExtents getFullWindowExtents();
|
||||||
CBox getWindowInputBox();
|
CBox getWindowBoxUnified(uint64_t props);
|
||||||
CBox getWindowMainSurfaceBox();
|
CBox getWindowMainSurfaceBox();
|
||||||
CBox getWindowIdealBoundingBoxIgnoreReserved();
|
CBox getWindowIdealBoundingBoxIgnoreReserved();
|
||||||
void addWindowDeco(std::unique_ptr<IHyprWindowDecoration> deco);
|
void addWindowDeco(std::unique_ptr<IHyprWindowDecoration> deco);
|
||||||
|
@ -356,7 +377,7 @@ class CWindow {
|
||||||
void createToplevelHandle();
|
void createToplevelHandle();
|
||||||
void destroyToplevelHandle();
|
void destroyToplevelHandle();
|
||||||
void updateToplevel();
|
void updateToplevel();
|
||||||
void updateSurfaceOutputs();
|
void updateSurfaceScaleTransformDetails();
|
||||||
void moveToWorkspace(int);
|
void moveToWorkspace(int);
|
||||||
CWindow* X11TransientFor();
|
CWindow* X11TransientFor();
|
||||||
void onUnmap();
|
void onUnmap();
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "../defines.hpp"
|
#include "../defines.hpp"
|
||||||
|
#include "../helpers/VarList.hpp"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
enum eConfigValueDataTypes {
|
enum eConfigValueDataTypes {
|
||||||
CVD_TYPE_INVALID = -1,
|
CVD_TYPE_INVALID = -1,
|
||||||
CVD_TYPE_GRADIENT = 0
|
CVD_TYPE_GRADIENT = 0,
|
||||||
|
CVD_TYPE_CSS_VALUE = 1
|
||||||
};
|
};
|
||||||
|
|
||||||
class ICustomConfigValueData {
|
class ICustomConfigValueData {
|
||||||
|
@ -50,3 +52,55 @@ class CGradientValueData : public ICustomConfigValueData {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class CCssGapData : public ICustomConfigValueData {
|
||||||
|
public:
|
||||||
|
CCssGapData() : top(0), right(0), bottom(0), left(0){};
|
||||||
|
CCssGapData(int64_t global) : top(global), right(global), bottom(global), left(global){};
|
||||||
|
CCssGapData(int64_t vertical, int64_t horizontal) : top(vertical), right(horizontal), bottom(vertical), left(horizontal){};
|
||||||
|
CCssGapData(int64_t top, int64_t horizontal, int64_t bottom) : top(top), right(horizontal), bottom(bottom), left(horizontal){};
|
||||||
|
CCssGapData(int64_t top, int64_t right, int64_t bottom, int64_t left) : top(top), right(right), bottom(bottom), left(left){};
|
||||||
|
|
||||||
|
/* Css like directions */
|
||||||
|
int64_t top;
|
||||||
|
int64_t right;
|
||||||
|
int64_t bottom;
|
||||||
|
int64_t left;
|
||||||
|
|
||||||
|
void parseGapData(CVarList varlist) {
|
||||||
|
switch (varlist.size()) {
|
||||||
|
case 1: {
|
||||||
|
*this = CCssGapData(std::stoi(varlist[0]));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 2: {
|
||||||
|
*this = CCssGapData(std::stoi(varlist[0]), std::stoi(varlist[1]));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 3: {
|
||||||
|
*this = CCssGapData(std::stoi(varlist[0]), std::stoi(varlist[1]), std::stoi(varlist[2]));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 4: {
|
||||||
|
*this = CCssGapData(std::stoi(varlist[0]), std::stoi(varlist[1]), std::stoi(varlist[2]), std::stoi(varlist[3]));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
Debug::log(WARN, "Too many arguments provided for gaps.");
|
||||||
|
*this = CCssGapData(std::stoi(varlist[0]), std::stoi(varlist[1]), std::stoi(varlist[2]), std::stoi(varlist[3]));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset(int64_t global) {
|
||||||
|
top = global;
|
||||||
|
right = global;
|
||||||
|
bottom = global;
|
||||||
|
left = global;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual eConfigValueDataTypes getDataType() {
|
||||||
|
return CVD_TYPE_CSS_VALUE;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
|
@ -21,21 +21,13 @@
|
||||||
#include "defaultConfig.hpp"
|
#include "defaultConfig.hpp"
|
||||||
#include "ConfigDataValues.hpp"
|
#include "ConfigDataValues.hpp"
|
||||||
|
|
||||||
|
#include <hyprlang.hpp>
|
||||||
|
|
||||||
#define INITANIMCFG(name) animationConfig[name] = {}
|
#define INITANIMCFG(name) animationConfig[name] = {}
|
||||||
#define CREATEANIMCFG(name, parent) animationConfig[name] = {false, "", "", 0.f, -1, &animationConfig["global"], &animationConfig[parent]}
|
#define CREATEANIMCFG(name, parent) animationConfig[name] = {false, "", "", 0.f, -1, &animationConfig["global"], &animationConfig[parent]}
|
||||||
|
|
||||||
#define HANDLE void*
|
#define HANDLE void*
|
||||||
|
|
||||||
struct SConfigValue {
|
|
||||||
int64_t intValue = -INT64_MAX;
|
|
||||||
float floatValue = -__FLT_MAX__;
|
|
||||||
std::string strValue = "";
|
|
||||||
Vector2D vecValue = Vector2D(-__FLT_MAX__, -__FLT_MAX__);
|
|
||||||
std::shared_ptr<ICustomConfigValueData> data;
|
|
||||||
|
|
||||||
bool set = false; // used for device configs
|
|
||||||
};
|
|
||||||
|
|
||||||
struct SWorkspaceRule {
|
struct SWorkspaceRule {
|
||||||
std::string monitor = "";
|
std::string monitor = "";
|
||||||
std::string workspaceString = "";
|
std::string workspaceString = "";
|
||||||
|
@ -43,14 +35,15 @@ struct SWorkspaceRule {
|
||||||
int workspaceId = -1;
|
int workspaceId = -1;
|
||||||
bool isDefault = false;
|
bool isDefault = false;
|
||||||
bool isPersistent = false;
|
bool isPersistent = false;
|
||||||
std::optional<int64_t> gapsIn;
|
std::optional<CCssGapData> gapsIn;
|
||||||
std::optional<int64_t> gapsOut;
|
std::optional<CCssGapData> gapsOut;
|
||||||
std::optional<int64_t> borderSize;
|
std::optional<int64_t> borderSize;
|
||||||
std::optional<int> border;
|
std::optional<int> border;
|
||||||
std::optional<int> rounding;
|
std::optional<int> rounding;
|
||||||
std::optional<int> decorate;
|
std::optional<int> decorate;
|
||||||
std::optional<int> shadow;
|
std::optional<int> shadow;
|
||||||
std::optional<std::string> onCreatedEmptyRunCmd;
|
std::optional<std::string> onCreatedEmptyRunCmd;
|
||||||
|
std::optional<std::string> defaultName;
|
||||||
std::map<std::string, std::string> layoutopts;
|
std::map<std::string, std::string> layoutopts;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -74,9 +67,14 @@ struct SAnimationPropertyConfig {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SPluginKeyword {
|
struct SPluginKeyword {
|
||||||
HANDLE handle = 0;
|
HANDLE handle = 0;
|
||||||
std::string name = "";
|
std::string name = "";
|
||||||
std::function<void(const std::string&, const std::string&)> fn;
|
Hyprlang::PCONFIGHANDLERFUNC fn = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SPluginVariable {
|
||||||
|
HANDLE handle = 0;
|
||||||
|
std::string name = "";
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SExecRequestedRule {
|
struct SExecRequestedRule {
|
||||||
|
@ -91,28 +89,21 @@ class CConfigManager {
|
||||||
void tick();
|
void tick();
|
||||||
void init();
|
void init();
|
||||||
|
|
||||||
int getInt(const std::string&);
|
|
||||||
float getFloat(const std::string&);
|
|
||||||
Vector2D getVec(const std::string&);
|
|
||||||
std::string getString(const std::string&);
|
|
||||||
void setFloat(const std::string&, float);
|
|
||||||
void setInt(const std::string&, int);
|
|
||||||
void setVec(const std::string&, Vector2D);
|
|
||||||
void setString(const std::string&, const std::string&);
|
|
||||||
|
|
||||||
int getDeviceInt(const std::string&, const std::string&, const std::string& fallback = "");
|
int getDeviceInt(const std::string&, const std::string&, const std::string& fallback = "");
|
||||||
float getDeviceFloat(const std::string&, const std::string&, const std::string& fallback = "");
|
float getDeviceFloat(const std::string&, const std::string&, const std::string& fallback = "");
|
||||||
Vector2D getDeviceVec(const std::string&, const std::string&, const std::string& fallback = "");
|
Vector2D getDeviceVec(const std::string&, const std::string&, const std::string& fallback = "");
|
||||||
std::string getDeviceString(const std::string&, const std::string&, const std::string& fallback = "");
|
std::string getDeviceString(const std::string&, const std::string&, const std::string& fallback = "");
|
||||||
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);
|
||||||
bool shouldBlurLS(const std::string&);
|
bool shouldBlurLS(const std::string&);
|
||||||
|
|
||||||
SConfigValue* getConfigValuePtr(const std::string&);
|
void* const* getConfigValuePtr(const std::string&);
|
||||||
SConfigValue* getConfigValuePtrSafe(const std::string&);
|
Hyprlang::CConfigValue* getHyprlangConfigValuePtr(const std::string& name, const std::string& specialCat = "");
|
||||||
|
void onPluginLoadUnload(const std::string& name, bool load);
|
||||||
static std::string getConfigDir();
|
static std::string getConfigDir();
|
||||||
static std::string getMainConfigPath();
|
static std::string getMainConfigPath();
|
||||||
|
|
||||||
SMonitorRule getMonitorRuleFor(const std::string&, const std::string& displayName = "");
|
SMonitorRule getMonitorRuleFor(const CMonitor&);
|
||||||
SWorkspaceRule getWorkspaceRuleFor(CWorkspace*);
|
SWorkspaceRule getWorkspaceRuleFor(CWorkspace*);
|
||||||
std::string getDefaultWorkspaceFor(const std::string&);
|
std::string getDefaultWorkspaceFor(const std::string&);
|
||||||
|
|
||||||
|
@ -120,15 +111,15 @@ class CConfigManager {
|
||||||
std::string getBoundMonitorStringForWS(const std::string&);
|
std::string getBoundMonitorStringForWS(const std::string&);
|
||||||
const std::deque<SWorkspaceRule>& getAllWorkspaceRules();
|
const std::deque<SWorkspaceRule>& getAllWorkspaceRules();
|
||||||
|
|
||||||
std::vector<SWindowRule> getMatchingRules(CWindow*);
|
std::vector<SWindowRule> getMatchingRules(CWindow*, bool dynamic = true);
|
||||||
std::vector<SLayerRule> getMatchingRules(SLayerSurface*);
|
std::vector<SLayerRule> getMatchingRules(SLayerSurface*);
|
||||||
|
|
||||||
std::unordered_map<std::string, SMonitorAdditionalReservedArea> m_mAdditionalReservedAreas;
|
std::unordered_map<std::string, SMonitorAdditionalReservedArea> m_mAdditionalReservedAreas;
|
||||||
|
|
||||||
std::unordered_map<std::string, SAnimationPropertyConfig> getAnimationConfig();
|
std::unordered_map<std::string, SAnimationPropertyConfig> getAnimationConfig();
|
||||||
|
|
||||||
void addPluginConfigVar(HANDLE handle, const std::string& name, const SConfigValue& value);
|
void addPluginConfigVar(HANDLE handle, const std::string& name, const Hyprlang::CConfigValue& value);
|
||||||
void addPluginKeyword(HANDLE handle, const std::string& name, std::function<void(const std::string& cmd, const std::string& val)> fun);
|
void addPluginKeyword(HANDLE handle, const std::string& name, Hyprlang::PCONFIGHANDLERFUNC fun, Hyprlang::SHandlerOptions opts = {});
|
||||||
void removePluginConfig(HANDLE handle);
|
void removePluginConfig(HANDLE handle);
|
||||||
|
|
||||||
// no-op when done.
|
// no-op when done.
|
||||||
|
@ -141,7 +132,7 @@ class CConfigManager {
|
||||||
void ensureMonitorStatus();
|
void ensureMonitorStatus();
|
||||||
void ensureVRR(CMonitor* pMonitor = nullptr);
|
void ensureVRR(CMonitor* pMonitor = nullptr);
|
||||||
|
|
||||||
std::string parseKeyword(const std::string&, const std::string&, bool dynamic = false);
|
std::string parseKeyword(const std::string&, const std::string&);
|
||||||
|
|
||||||
void addParseError(const std::string&);
|
void addParseError(const std::string&);
|
||||||
|
|
||||||
|
@ -151,77 +142,65 @@ class CConfigManager {
|
||||||
|
|
||||||
void handlePluginLoads();
|
void handlePluginLoads();
|
||||||
|
|
||||||
std::string configCurrentPath;
|
// keywords
|
||||||
|
std::optional<std::string> handleRawExec(const std::string&, const std::string&);
|
||||||
|
std::optional<std::string> handleExecOnce(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> 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> handleWindowRuleV2(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> handleAnimation(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> handleBlurLS(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> handlePlugin(const std::string&, const std::string&);
|
||||||
|
|
||||||
|
std::string configCurrentPath;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::deque<std::string> configPaths; // stores all the config paths
|
std::unique_ptr<Hyprlang::CConfig> m_pConfig;
|
||||||
std::unordered_map<std::string, time_t> configModifyTimes; // stores modify times
|
|
||||||
std::vector<std::pair<std::string, std::string>> configDynamicVars; // stores dynamic vars declared by the user
|
|
||||||
std::unordered_map<std::string, SConfigValue> configValues;
|
|
||||||
std::unordered_map<std::string, std::unordered_map<std::string, SConfigValue>> deviceConfigs; // stores device configs
|
|
||||||
|
|
||||||
std::unordered_map<std::string, SAnimationPropertyConfig> animationConfig; // stores all the animations with their set values
|
std::deque<std::string> configPaths; // stores all the config paths
|
||||||
|
std::unordered_map<std::string, time_t> configModifyTimes; // stores modify times
|
||||||
|
|
||||||
std::string currentCategory = ""; // For storing the category of the current item
|
std::unordered_map<std::string, SAnimationPropertyConfig> animationConfig; // stores all the animations with their set values
|
||||||
|
|
||||||
std::string parseError = ""; // For storing a parse error to display later
|
std::string m_szCurrentSubmap = ""; // For storing the current keybind submap
|
||||||
|
|
||||||
std::string m_szCurrentSubmap = ""; // For storing the current keybind submap
|
std::vector<SExecRequestedRule> execRequestedRules; // rules requested with exec, e.g. [workspace 2] kitty
|
||||||
|
|
||||||
std::vector<SExecRequestedRule> execRequestedRules; // rules requested with exec, e.g. [workspace 2] kitty
|
std::vector<std::string> m_vDeclaredPlugins;
|
||||||
|
std::vector<SPluginKeyword> pluginKeywords;
|
||||||
|
std::vector<SPluginVariable> pluginVariables;
|
||||||
|
|
||||||
std::vector<std::string> m_vDeclaredPlugins;
|
bool isFirstLaunch = true; // For exec-once
|
||||||
std::unordered_map<HANDLE, std::unique_ptr<std::unordered_map<std::string, SConfigValue>>> pluginConfigs; // stores plugin configs
|
|
||||||
std::vector<SPluginKeyword> pluginKeywords;
|
|
||||||
|
|
||||||
bool isFirstLaunch = true; // For exec-once
|
std::deque<SMonitorRule> m_dMonitorRules;
|
||||||
|
std::deque<SWorkspaceRule> m_dWorkspaceRules;
|
||||||
|
std::deque<SWindowRule> m_dWindowRules;
|
||||||
|
std::deque<SLayerRule> m_dLayerRules;
|
||||||
|
std::deque<std::string> m_dBlurLSNamespaces;
|
||||||
|
|
||||||
std::deque<SMonitorRule> m_dMonitorRules;
|
bool firstExecDispatched = false;
|
||||||
std::deque<SWorkspaceRule> m_dWorkspaceRules;
|
bool m_bManualCrashInitiated = false;
|
||||||
std::deque<SWindowRule> m_dWindowRules;
|
std::deque<std::string> firstExecRequests;
|
||||||
std::deque<SLayerRule> m_dLayerRules;
|
|
||||||
std::deque<std::string> m_dBlurLSNamespaces;
|
|
||||||
|
|
||||||
bool firstExecDispatched = false;
|
std::vector<std::pair<std::string, std::string>> m_vFailedPluginConfigValues; // for plugin values of unloaded plugins
|
||||||
bool m_bManualCrashInitiated = false;
|
|
||||||
std::deque<std::string> firstExecRequests;
|
|
||||||
|
|
||||||
std::vector<std::pair<std::string, std::string>> environmentVariables;
|
|
||||||
|
|
||||||
std::vector<std::pair<std::string, std::string>> m_vFailedPluginConfigValues; // for plugin values of unloaded plugins
|
|
||||||
|
|
||||||
// internal methods
|
// internal methods
|
||||||
void setDefaultVars();
|
void setAnimForChildren(SAnimationPropertyConfig* const);
|
||||||
void setDefaultAnimationVars();
|
void updateBlurredLS(const std::string&, const bool);
|
||||||
void setDeviceDefaultVars(const std::string&);
|
void setDefaultAnimationVars();
|
||||||
void populateEnvironment();
|
std::optional<std::string> resetHLConfig();
|
||||||
|
std::optional<std::string> verifyConfigExists();
|
||||||
void setAnimForChildren(SAnimationPropertyConfig* const);
|
void postConfigReload(const Hyprlang::CParseResult& result);
|
||||||
void updateBlurredLS(const std::string&, const bool);
|
void reload();
|
||||||
|
|
||||||
void applyUserDefinedVars(std::string&, const size_t);
|
|
||||||
void loadConfigLoadVars();
|
|
||||||
SConfigValue getConfigValueSafe(const std::string&);
|
|
||||||
SConfigValue getConfigValueSafeDevice(const std::string&, const std::string&, const std::string& fallback = "");
|
|
||||||
void parseLine(std::string&);
|
|
||||||
void configSetValueSafe(const std::string&, const std::string&);
|
|
||||||
void handleDeviceConfig(const std::string&, const std::string&);
|
|
||||||
void handleRawExec(const std::string&, const std::string&);
|
|
||||||
void handleMonitor(const std::string&, const std::string&);
|
|
||||||
void handleBind(const std::string&, const std::string&);
|
|
||||||
void handleUnbind(const std::string&, const std::string&);
|
|
||||||
void handleWindowRule(const std::string&, const std::string&);
|
|
||||||
void handleLayerRule(const std::string&, const std::string&);
|
|
||||||
void handleWindowRuleV2(const std::string&, const std::string&);
|
|
||||||
void handleWorkspaceRules(const std::string&, const std::string&);
|
|
||||||
void handleBezier(const std::string&, const std::string&);
|
|
||||||
void handleAnimation(const std::string&, const std::string&);
|
|
||||||
void handleSource(const std::string&, const std::string&);
|
|
||||||
void handleSubmap(const std::string&, const std::string&);
|
|
||||||
void handleBlurLS(const std::string&, const std::string&);
|
|
||||||
void handleBindWS(const std::string&, const std::string&);
|
|
||||||
void handleEnv(const std::string&, const std::string&);
|
|
||||||
void handlePlugin(const std::string&, const std::string&);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
inline std::unique_ptr<CConfigManager> g_pConfigManager;
|
inline std::unique_ptr<CConfigManager> g_pConfigManager;
|
||||||
|
|
|
@ -3,11 +3,11 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
inline const std::string AUTOCONFIG = R"#(
|
inline const std::string AUTOCONFIG = R"#(
|
||||||
########################################################################################
|
# #######################################################################################
|
||||||
AUTOGENERATED HYPR CONFIG.
|
# AUTOGENERATED HYPR CONFIG.
|
||||||
PLEASE USE THE CONFIG PROVIDED IN THE GIT REPO /examples/hypr.conf AND EDIT IT,
|
# PLEASE USE THE CONFIG PROVIDED IN THE GIT REPO /examples/hypr.conf AND EDIT IT,
|
||||||
OR EDIT THIS ONE ACCORDING TO THE WIKI INSTRUCTIONS.
|
# OR EDIT THIS ONE ACCORDING TO THE WIKI INSTRUCTIONS.
|
||||||
########################################################################################
|
# #######################################################################################
|
||||||
|
|
||||||
#
|
#
|
||||||
# Please note not all available settings / options are set here.
|
# Please note not all available settings / options are set here.
|
||||||
|
@ -51,7 +51,7 @@ input {
|
||||||
natural_scroll = no
|
natural_scroll = no
|
||||||
}
|
}
|
||||||
|
|
||||||
sensitivity = 0 # -1.0 - 1.0, 0 means no modification.
|
sensitivity = 0 # -1.0 to 1.0, 0 means no modification.
|
||||||
}
|
}
|
||||||
|
|
||||||
general {
|
general {
|
||||||
|
@ -119,12 +119,13 @@ gestures {
|
||||||
|
|
||||||
misc {
|
misc {
|
||||||
# See https://wiki.hyprland.org/Configuring/Variables/ for more
|
# See https://wiki.hyprland.org/Configuring/Variables/ for more
|
||||||
force_default_wallpaper = -1 # Set to 0 to disable the anime mascot wallpapers
|
force_default_wallpaper = -1 # Set to 0 or 1 to disable the anime mascot wallpapers
|
||||||
}
|
}
|
||||||
|
|
||||||
# Example per-device config
|
# Example per-device config
|
||||||
# See https://wiki.hyprland.org/Configuring/Keywords/#executing for more
|
# See https://wiki.hyprland.org/Configuring/Keywords/#executing for more
|
||||||
device:epic-mouse-v1 {
|
device {
|
||||||
|
name = epic-mouse-v1
|
||||||
sensitivity = -0.5
|
sensitivity = -0.5
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,7 +134,7 @@ device:epic-mouse-v1 {
|
||||||
# Example windowrule v2
|
# Example windowrule v2
|
||||||
# windowrulev2 = float,class:^(kitty)$,title:^(kitty)$
|
# windowrulev2 = float,class:^(kitty)$,title:^(kitty)$
|
||||||
# See https://wiki.hyprland.org/Configuring/Window-Rules/ for more
|
# See https://wiki.hyprland.org/Configuring/Window-Rules/ for more
|
||||||
windowrulev2 = nomaximizerequest, class:.* # You'll probably like this.
|
windowrulev2 = suppressevent maximize, class:.* # You'll probably like this.
|
||||||
|
|
||||||
|
|
||||||
# See https://wiki.hyprland.org/Configuring/Keywords/ for more
|
# See https://wiki.hyprland.org/Configuring/Keywords/ for more
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include <sys/utsname.h>
|
#include <sys/utsname.h>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
#include <link.h>
|
||||||
|
|
||||||
#include "../plugins/PluginSystem.hpp"
|
#include "../plugins/PluginSystem.hpp"
|
||||||
|
|
||||||
|
@ -105,21 +106,38 @@ void CrashReporter::createAndSaveCrash(int sig) {
|
||||||
const auto FPATH = std::filesystem::canonical("/proc/self/exe");
|
const auto FPATH = std::filesystem::canonical("/proc/self/exe");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
std::string addrs = "";
|
||||||
for (size_t i = 0; i < CALLSTACK.size(); ++i) {
|
for (size_t i = 0; i < CALLSTACK.size(); ++i) {
|
||||||
finalCrashReport += std::format("\t#{} | {}\n", i, CALLSTACK[i].desc);
|
// convert in memory address to VMA address
|
||||||
|
Dl_info info;
|
||||||
|
struct link_map* linkMap;
|
||||||
|
dladdr1((void*)CALLSTACK[i].adr, &info, (void**)&linkMap, RTLD_DL_LINKMAP);
|
||||||
|
size_t vmaAddr = (size_t)CALLSTACK[i].adr - linkMap->l_addr;
|
||||||
|
|
||||||
|
addrs += std::format("0x{:x} ", vmaAddr);
|
||||||
|
}
|
||||||
#ifdef __clang__
|
#ifdef __clang__
|
||||||
const auto CMD = std::format("llvm-addr2line -e {} -f 0x{:x}", FPATH.c_str(), (uint64_t)CALLSTACK[i].adr);
|
const auto CMD = std::format("llvm-addr2line -e {} -Cf {}", FPATH.c_str(), addrs);
|
||||||
#else
|
#else
|
||||||
const auto CMD = std::format("addr2line -e {} -f 0x{:x}", FPATH.c_str(), (uint64_t)CALLSTACK[i].adr);
|
const auto CMD = std::format("addr2line -e {} -Cf {}", FPATH.c_str(), addrs);
|
||||||
#endif
|
#endif
|
||||||
const auto ADDR2LINE = replaceInString(execAndGet(CMD.c_str()), "\n", "\n\t\t");
|
|
||||||
finalCrashReport += "\t\t" + ADDR2LINE.substr(0, ADDR2LINE.length() - 2);
|
const auto ADDR2LINE = execAndGet(CMD.c_str());
|
||||||
|
|
||||||
|
std::stringstream ssin(ADDR2LINE);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < CALLSTACK.size(); ++i) {
|
||||||
|
finalCrashReport += std::format("\t#{} | {}", i, CALLSTACK[i].desc);
|
||||||
|
std::string functionInfo;
|
||||||
|
std::string fileLineInfo;
|
||||||
|
std::getline(ssin, functionInfo);
|
||||||
|
std::getline(ssin, fileLineInfo);
|
||||||
|
finalCrashReport += std::format("\n\t\t{}\n\t\t{}\n", functionInfo, fileLineInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
finalCrashReport += "\n\nLog tail:\n";
|
finalCrashReport += "\n\nLog tail:\n";
|
||||||
|
|
||||||
finalCrashReport += Debug::rollingLog;
|
finalCrashReport += Debug::rollingLog.substr(Debug::rollingLog.find("\n") + 1);
|
||||||
|
|
||||||
const auto HOME = getenv("HOME");
|
const auto HOME = getenv("HOME");
|
||||||
const auto CACHE_HOME = getenv("XDG_CACHE_HOME");
|
const auto CACHE_HOME = getenv("XDG_CACHE_HOME");
|
||||||
|
@ -128,21 +146,18 @@ void CrashReporter::createAndSaveCrash(int sig) {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
std::ofstream ofs;
|
std::ofstream ofs;
|
||||||
std::string path;
|
std::string reportDir;
|
||||||
if (!CACHE_HOME || std::string(CACHE_HOME).empty()) {
|
|
||||||
if (!std::filesystem::exists(std::string(HOME) + "/.hyprland"))
|
|
||||||
std::filesystem::create_directory(std::string(HOME) + "/.hyprland");
|
|
||||||
|
|
||||||
path = std::string(HOME) + "/.hyprland/hyprlandCrashReport" + std::to_string(PID) + ".txt";
|
if (!CACHE_HOME || std::string(CACHE_HOME).empty())
|
||||||
ofs.open(path, std::ios::trunc);
|
reportDir = std::string(HOME) + "/.cache/hyprland";
|
||||||
|
else
|
||||||
|
reportDir = std::string(CACHE_HOME) + "/hyprland";
|
||||||
|
|
||||||
} else {
|
if (!std::filesystem::exists(reportDir))
|
||||||
if (!std::filesystem::exists(std::string(CACHE_HOME) + "/hyprland"))
|
std::filesystem::create_directory(reportDir);
|
||||||
std::filesystem::create_directory(std::string(CACHE_HOME) + "/hyprland");
|
const auto path = reportDir + "/hyprlandCrashReport" + std::to_string(PID) + ".txt";
|
||||||
|
|
||||||
path = std::string(CACHE_HOME) + "/hyprland/hyprlandCrashReport" + std::to_string(PID) + ".txt";
|
ofs.open(path, std::ios::trunc);
|
||||||
ofs.open(path, std::ios::trunc);
|
|
||||||
}
|
|
||||||
|
|
||||||
ofs << finalCrashReport;
|
ofs << finalCrashReport;
|
||||||
|
|
||||||
|
|
|
@ -7,12 +7,13 @@
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#include <sys/utsname.h>
|
||||||
#include <sys/un.h>
|
#include <sys/un.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <typeindex>
|
||||||
|
|
||||||
static void trimTrailingComma(std::string& str) {
|
static void trimTrailingComma(std::string& str) {
|
||||||
if (!str.empty() && str.back() == ',')
|
if (!str.empty() && str.back() == ',')
|
||||||
|
@ -28,7 +29,7 @@ static std::string getWorkspaceNameFromSpecialID(const int workspaceID) {
|
||||||
return workspace->m_szName;
|
return workspace->m_szName;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string monitorsRequest(std::string request, HyprCtl::eHyprCtlOutputFormat format) {
|
std::string monitorsRequest(eHyprCtlOutputFormat format, std::string request) {
|
||||||
CVarList vars(request, 0, ' ');
|
CVarList vars(request, 0, ' ');
|
||||||
auto allMonitors = false;
|
auto allMonitors = false;
|
||||||
|
|
||||||
|
@ -39,7 +40,7 @@ std::string monitorsRequest(std::string request, HyprCtl::eHyprCtlOutputFormat f
|
||||||
allMonitors = true;
|
allMonitors = true;
|
||||||
|
|
||||||
std::string result = "";
|
std::string result = "";
|
||||||
if (format == HyprCtl::FORMAT_JSON) {
|
if (format == eHyprCtlOutputFormat::FORMAT_JSON) {
|
||||||
result += "[";
|
result += "[";
|
||||||
|
|
||||||
for (auto& m : allMonitors ? g_pCompositor->m_vRealMonitors : g_pCompositor->m_vMonitors) {
|
for (auto& m : allMonitors ? g_pCompositor->m_vRealMonitors : g_pCompositor->m_vMonitors) {
|
||||||
|
@ -75,7 +76,7 @@ std::string monitorsRequest(std::string request, HyprCtl::eHyprCtlOutputFormat f
|
||||||
"vrr": {},
|
"vrr": {},
|
||||||
"activelyTearing": {}
|
"activelyTearing": {}
|
||||||
}},)#",
|
}},)#",
|
||||||
m->ID, escapeJSONStrings(m->szName), escapeJSONStrings(m->szDescription), (m->output->make ? m->output->make : ""), (m->output->model ? m->output->model : ""),
|
m->ID, escapeJSONStrings(m->szName), escapeJSONStrings(m->szShortDescription), (m->output->make ? m->output->make : ""), (m->output->model ? m->output->model : ""),
|
||||||
(m->output->serial ? m->output->serial : ""), (int)m->vecPixelSize.x, (int)m->vecPixelSize.y, m->refreshRate, (int)m->vecPosition.x, (int)m->vecPosition.y,
|
(m->output->serial ? m->output->serial : ""), (int)m->vecPixelSize.x, (int)m->vecPixelSize.y, m->refreshRate, (int)m->vecPosition.x, (int)m->vecPosition.y,
|
||||||
m->activeWorkspace, (m->activeWorkspace == -1 ? "" : escapeJSONStrings(g_pCompositor->getWorkspaceByID(m->activeWorkspace)->m_szName)), m->specialWorkspaceID,
|
m->activeWorkspace, (m->activeWorkspace == -1 ? "" : escapeJSONStrings(g_pCompositor->getWorkspaceByID(m->activeWorkspace)->m_szName)), m->specialWorkspaceID,
|
||||||
escapeJSONStrings(getWorkspaceNameFromSpecialID(m->specialWorkspaceID)), (int)m->vecReservedTopLeft.x, (int)m->vecReservedTopLeft.y,
|
escapeJSONStrings(getWorkspaceNameFromSpecialID(m->specialWorkspaceID)), (int)m->vecReservedTopLeft.x, (int)m->vecReservedTopLeft.y,
|
||||||
|
@ -97,7 +98,7 @@ std::string monitorsRequest(std::string request, HyprCtl::eHyprCtlOutputFormat f
|
||||||
"workspace: {} ({})\n\treserved: {} "
|
"workspace: {} ({})\n\treserved: {} "
|
||||||
"{} {} {}\n\tscale: {:.2f}\n\ttransform: "
|
"{} {} {}\n\tscale: {:.2f}\n\ttransform: "
|
||||||
"{}\n\tfocused: {}\n\tdpmsStatus: {}\n\tvrr: {}\n\tactivelyTearing: {}\n\n",
|
"{}\n\tfocused: {}\n\tdpmsStatus: {}\n\tvrr: {}\n\tactivelyTearing: {}\n\n",
|
||||||
m->szName, m->ID, (int)m->vecPixelSize.x, (int)m->vecPixelSize.y, m->refreshRate, (int)m->vecPosition.x, (int)m->vecPosition.y, m->szDescription,
|
m->szName, m->ID, (int)m->vecPixelSize.x, (int)m->vecPixelSize.y, m->refreshRate, (int)m->vecPosition.x, (int)m->vecPosition.y, m->szShortDescription,
|
||||||
(m->output->make ? m->output->make : ""), (m->output->model ? m->output->model : ""), (m->output->serial ? m->output->serial : ""), m->activeWorkspace,
|
(m->output->make ? m->output->make : ""), (m->output->model ? m->output->model : ""), (m->output->serial ? m->output->serial : ""), m->activeWorkspace,
|
||||||
(m->activeWorkspace == -1 ? "" : g_pCompositor->getWorkspaceByID(m->activeWorkspace)->m_szName), m->specialWorkspaceID,
|
(m->activeWorkspace == -1 ? "" : g_pCompositor->getWorkspaceByID(m->activeWorkspace)->m_szName), m->specialWorkspaceID,
|
||||||
getWorkspaceNameFromSpecialID(m->specialWorkspaceID), (int)m->vecReservedTopLeft.x, (int)m->vecReservedTopLeft.y, (int)m->vecReservedBottomRight.x,
|
getWorkspaceNameFromSpecialID(m->specialWorkspaceID), (int)m->vecReservedTopLeft.x, (int)m->vecReservedTopLeft.y, (int)m->vecReservedBottomRight.x,
|
||||||
|
@ -109,8 +110,8 @@ std::string monitorsRequest(std::string request, HyprCtl::eHyprCtlOutputFormat f
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string getGroupedData(CWindow* w, HyprCtl::eHyprCtlOutputFormat format) {
|
static std::string getGroupedData(CWindow* w, eHyprCtlOutputFormat format) {
|
||||||
const bool isJson = format == HyprCtl::FORMAT_JSON;
|
const bool isJson = format == eHyprCtlOutputFormat::FORMAT_JSON;
|
||||||
if (!w->m_sGroupData.pNextWindow)
|
if (!w->m_sGroupData.pNextWindow)
|
||||||
return isJson ? "" : "0";
|
return isJson ? "" : "0";
|
||||||
|
|
||||||
|
@ -133,7 +134,7 @@ static std::string getGroupedData(CWindow* w, HyprCtl::eHyprCtlOutputFormat form
|
||||||
return result.str();
|
return result.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string getWindowData(CWindow* w, HyprCtl::eHyprCtlOutputFormat format) {
|
static std::string getWindowData(CWindow* w, eHyprCtlOutputFormat format) {
|
||||||
auto getFocusHistoryID = [](CWindow* wnd) -> int {
|
auto getFocusHistoryID = [](CWindow* wnd) -> int {
|
||||||
for (size_t i = 0; i < g_pCompositor->m_vWindowFocusHistory.size(); ++i) {
|
for (size_t i = 0; i < g_pCompositor->m_vWindowFocusHistory.size(); ++i) {
|
||||||
if (g_pCompositor->m_vWindowFocusHistory[i] == wnd)
|
if (g_pCompositor->m_vWindowFocusHistory[i] == wnd)
|
||||||
|
@ -142,7 +143,7 @@ static std::string getWindowData(CWindow* w, HyprCtl::eHyprCtlOutputFormat forma
|
||||||
return -1;
|
return -1;
|
||||||
};
|
};
|
||||||
|
|
||||||
if (format == HyprCtl::FORMAT_JSON) {
|
if (format == eHyprCtlOutputFormat::FORMAT_JSON) {
|
||||||
return std::format(
|
return std::format(
|
||||||
R"#({{
|
R"#({{
|
||||||
"address": "0x{:x}",
|
"address": "0x{:x}",
|
||||||
|
@ -170,8 +171,8 @@ static std::string getWindowData(CWindow* w, HyprCtl::eHyprCtlOutputFormat forma
|
||||||
"swallowing": "0x{:x}",
|
"swallowing": "0x{:x}",
|
||||||
"focusHistoryID": {}
|
"focusHistoryID": {}
|
||||||
}},)#",
|
}},)#",
|
||||||
(uintptr_t)w, (w->m_bIsMapped ? "true" : "false"), (w->isHidden() ? "true" : "false"), (int)w->m_vRealPosition.goalv().x, (int)w->m_vRealPosition.goalv().y,
|
(uintptr_t)w, (w->m_bIsMapped ? "true" : "false"), (w->isHidden() ? "true" : "false"), (int)w->m_vRealPosition.goal().x, (int)w->m_vRealPosition.goal().y,
|
||||||
(int)w->m_vRealSize.goalv().x, (int)w->m_vRealSize.goalv().y, w->m_iWorkspaceID,
|
(int)w->m_vRealSize.goal().x, (int)w->m_vRealSize.goal().y, w->m_iWorkspaceID,
|
||||||
escapeJSONStrings(w->m_iWorkspaceID == -1 ? "" :
|
escapeJSONStrings(w->m_iWorkspaceID == -1 ? "" :
|
||||||
g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID) ? g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID)->m_szName :
|
g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID) ? g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID)->m_szName :
|
||||||
std::string("Invalid workspace " + std::to_string(w->m_iWorkspaceID))),
|
std::string("Invalid workspace " + std::to_string(w->m_iWorkspaceID))),
|
||||||
|
@ -186,8 +187,8 @@ static std::string getWindowData(CWindow* w, HyprCtl::eHyprCtlOutputFormat forma
|
||||||
"{}\n\tinitialClass: {}\n\tinitialTitle: {}\n\tpid: "
|
"{}\n\tinitialClass: {}\n\tinitialTitle: {}\n\tpid: "
|
||||||
"{}\n\txwayland: {}\n\tpinned: "
|
"{}\n\txwayland: {}\n\tpinned: "
|
||||||
"{}\n\tfullscreen: {}\n\tfullscreenmode: {}\n\tfakefullscreen: {}\n\tgrouped: {}\n\tswallowing: {:x}\n\tfocusHistoryID: {}\n\n",
|
"{}\n\tfullscreen: {}\n\tfullscreenmode: {}\n\tfakefullscreen: {}\n\tgrouped: {}\n\tswallowing: {:x}\n\tfocusHistoryID: {}\n\n",
|
||||||
(uintptr_t)w, w->m_szTitle, (int)w->m_bIsMapped, (int)w->isHidden(), (int)w->m_vRealPosition.goalv().x, (int)w->m_vRealPosition.goalv().y,
|
(uintptr_t)w, w->m_szTitle, (int)w->m_bIsMapped, (int)w->isHidden(), (int)w->m_vRealPosition.goal().x, (int)w->m_vRealPosition.goal().y, (int)w->m_vRealSize.goal().x,
|
||||||
(int)w->m_vRealSize.goalv().x, (int)w->m_vRealSize.goalv().y, w->m_iWorkspaceID,
|
(int)w->m_vRealSize.goal().y, w->m_iWorkspaceID,
|
||||||
(w->m_iWorkspaceID == -1 ? "" :
|
(w->m_iWorkspaceID == -1 ? "" :
|
||||||
g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID) ? g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID)->m_szName :
|
g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID) ? g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID)->m_szName :
|
||||||
std::string("Invalid workspace " + std::to_string(w->m_iWorkspaceID))),
|
std::string("Invalid workspace " + std::to_string(w->m_iWorkspaceID))),
|
||||||
|
@ -198,9 +199,9 @@ static std::string getWindowData(CWindow* w, HyprCtl::eHyprCtlOutputFormat forma
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string clientsRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
std::string clientsRequest(eHyprCtlOutputFormat format, std::string request) {
|
||||||
std::string result = "";
|
std::string result = "";
|
||||||
if (format == HyprCtl::FORMAT_JSON) {
|
if (format == eHyprCtlOutputFormat::FORMAT_JSON) {
|
||||||
result += "[";
|
result += "[";
|
||||||
|
|
||||||
for (auto& w : g_pCompositor->m_vWindows) {
|
for (auto& w : g_pCompositor->m_vWindows) {
|
||||||
|
@ -218,10 +219,10 @@ std::string clientsRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string getWorkspaceData(CWorkspace* w, HyprCtl::eHyprCtlOutputFormat format) {
|
static std::string getWorkspaceData(CWorkspace* w, eHyprCtlOutputFormat format) {
|
||||||
const auto PLASTW = w->getLastFocusedWindow();
|
const auto PLASTW = w->getLastFocusedWindow();
|
||||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(w->m_iMonitorID);
|
const auto PMONITOR = g_pCompositor->getMonitorFromID(w->m_iMonitorID);
|
||||||
if (format == HyprCtl::FORMAT_JSON) {
|
if (format == eHyprCtlOutputFormat::FORMAT_JSON) {
|
||||||
return std::format(R"#({{
|
return std::format(R"#({{
|
||||||
"id": {},
|
"id": {},
|
||||||
"name": "{}",
|
"name": "{}",
|
||||||
|
@ -242,14 +243,18 @@ static std::string getWorkspaceData(CWorkspace* w, HyprCtl::eHyprCtlOutputFormat
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string getWorkspaceRuleData(const SWorkspaceRule& r, HyprCtl::eHyprCtlOutputFormat format) {
|
static std::string getWorkspaceRuleData(const SWorkspaceRule& r, eHyprCtlOutputFormat format) {
|
||||||
const auto boolToString = [](const bool b) -> std::string { return b ? "true" : "false"; };
|
const auto boolToString = [](const bool b) -> std::string { return b ? "true" : "false"; };
|
||||||
if (format == HyprCtl::FORMAT_JSON) {
|
if (format == eHyprCtlOutputFormat::FORMAT_JSON) {
|
||||||
const std::string monitor = r.monitor.empty() ? "" : std::format(",\n \"monitor\": \"{}\"", escapeJSONStrings(r.monitor));
|
const std::string monitor = r.monitor.empty() ? "" : std::format(",\n \"monitor\": \"{}\"", escapeJSONStrings(r.monitor));
|
||||||
const std::string default_ = (bool)(r.isDefault) ? std::format(",\n \"default\": {}", boolToString(r.isDefault)) : "";
|
const std::string default_ = (bool)(r.isDefault) ? std::format(",\n \"default\": {}", boolToString(r.isDefault)) : "";
|
||||||
const std::string persistent = (bool)(r.isPersistent) ? std::format(",\n \"persistent\": {}", boolToString(r.isPersistent)) : "";
|
const std::string persistent = (bool)(r.isPersistent) ? std::format(",\n \"persistent\": {}", boolToString(r.isPersistent)) : "";
|
||||||
const std::string gapsIn = (bool)(r.gapsIn) ? std::format(",\n \"gapsIn\": {}", r.gapsIn.value()) : "";
|
const std::string gapsIn = (bool)(r.gapsIn) ?
|
||||||
const std::string gapsOut = (bool)(r.gapsOut) ? std::format(",\n \"gapsOut\": {}", r.gapsOut.value()) : "";
|
std::format(",\n \"gapsIn\": [{}, {}, {}, {}]", r.gapsIn.value().top, r.gapsIn.value().right, r.gapsIn.value().bottom, r.gapsIn.value().left) :
|
||||||
|
"";
|
||||||
|
const std::string gapsOut = (bool)(r.gapsOut) ?
|
||||||
|
std::format(",\n \"gapsOut\": [{}, {}, {}, {}]", r.gapsOut.value().top, r.gapsOut.value().right, r.gapsOut.value().bottom, r.gapsOut.value().left) :
|
||||||
|
"";
|
||||||
const std::string borderSize = (bool)(r.borderSize) ? std::format(",\n \"borderSize\": {}", r.borderSize.value()) : "";
|
const std::string borderSize = (bool)(r.borderSize) ? std::format(",\n \"borderSize\": {}", r.borderSize.value()) : "";
|
||||||
const std::string border = (bool)(r.border) ? std::format(",\n \"border\": {}", boolToString(r.border.value())) : "";
|
const std::string border = (bool)(r.border) ? std::format(",\n \"border\": {}", boolToString(r.border.value())) : "";
|
||||||
const std::string rounding = (bool)(r.rounding) ? std::format(",\n \"rounding\": {}", boolToString(r.rounding.value())) : "";
|
const std::string rounding = (bool)(r.rounding) ? std::format(",\n \"rounding\": {}", boolToString(r.rounding.value())) : "";
|
||||||
|
@ -266,8 +271,12 @@ static std::string getWorkspaceRuleData(const SWorkspaceRule& r, HyprCtl::eHyprC
|
||||||
const std::string monitor = std::format("\tmonitor: {}\n", r.monitor.empty() ? "<unset>" : escapeJSONStrings(r.monitor));
|
const std::string monitor = std::format("\tmonitor: {}\n", r.monitor.empty() ? "<unset>" : escapeJSONStrings(r.monitor));
|
||||||
const std::string default_ = std::format("\tdefault: {}\n", (bool)(r.isDefault) ? boolToString(r.isDefault) : "<unset>");
|
const std::string default_ = std::format("\tdefault: {}\n", (bool)(r.isDefault) ? boolToString(r.isDefault) : "<unset>");
|
||||||
const std::string persistent = std::format("\tpersistent: {}\n", (bool)(r.isPersistent) ? boolToString(r.isPersistent) : "<unset>");
|
const std::string persistent = std::format("\tpersistent: {}\n", (bool)(r.isPersistent) ? boolToString(r.isPersistent) : "<unset>");
|
||||||
const std::string gapsIn = std::format("\tgapsIn: {}\n", (bool)(r.gapsIn) ? std::to_string(r.gapsIn.value()) : "<unset>");
|
const std::string gapsIn = (bool)(r.gapsIn) ? std::format("\tgapsIn: {} {} {} {}\n", std::to_string(r.gapsIn.value().top), std::to_string(r.gapsIn.value().right),
|
||||||
const std::string gapsOut = std::format("\tgapsOut: {}\n", (bool)(r.gapsOut) ? std::to_string(r.gapsOut.value()) : "<unset>");
|
std::to_string(r.gapsIn.value().bottom), std::to_string(r.gapsIn.value().left)) :
|
||||||
|
std::format("\tgapsIn: <unset>\n");
|
||||||
|
const std::string gapsOut = (bool)(r.gapsOut) ? std::format("\tgapsOut: {} {} {} {}\n", std::to_string(r.gapsOut.value().top), std::to_string(r.gapsOut.value().right),
|
||||||
|
std::to_string(r.gapsOut.value().bottom), std::to_string(r.gapsOut.value().left)) :
|
||||||
|
std::format("\tgapsOut: <unset>\n");
|
||||||
const std::string borderSize = std::format("\tborderSize: {}\n", (bool)(r.borderSize) ? std::to_string(r.borderSize.value()) : "<unset>");
|
const std::string borderSize = std::format("\tborderSize: {}\n", (bool)(r.borderSize) ? std::to_string(r.borderSize.value()) : "<unset>");
|
||||||
const std::string border = std::format("\tborder: {}\n", (bool)(r.border) ? boolToString(r.border.value()) : "<unset>");
|
const std::string border = std::format("\tborder: {}\n", (bool)(r.border) ? boolToString(r.border.value()) : "<unset>");
|
||||||
const std::string rounding = std::format("\trounding: {}\n", (bool)(r.rounding) ? boolToString(r.rounding.value()) : "<unset>");
|
const std::string rounding = std::format("\trounding: {}\n", (bool)(r.rounding) ? boolToString(r.rounding.value()) : "<unset>");
|
||||||
|
@ -280,7 +289,7 @@ static std::string getWorkspaceRuleData(const SWorkspaceRule& r, HyprCtl::eHyprC
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::string activeWorkspaceRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
std::string activeWorkspaceRequest(eHyprCtlOutputFormat format, std::string request) {
|
||||||
if (!g_pCompositor->m_pLastMonitor)
|
if (!g_pCompositor->m_pLastMonitor)
|
||||||
return "unsafe state";
|
return "unsafe state";
|
||||||
|
|
||||||
|
@ -293,10 +302,10 @@ std::string activeWorkspaceRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||||
return getWorkspaceData(w, format);
|
return getWorkspaceData(w, format);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string workspacesRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
std::string workspacesRequest(eHyprCtlOutputFormat format, std::string request) {
|
||||||
std::string result = "";
|
std::string result = "";
|
||||||
|
|
||||||
if (format == HyprCtl::FORMAT_JSON) {
|
if (format == eHyprCtlOutputFormat::FORMAT_JSON) {
|
||||||
result += "[";
|
result += "[";
|
||||||
for (auto& w : g_pCompositor->m_vWorkspaces) {
|
for (auto& w : g_pCompositor->m_vWorkspaces) {
|
||||||
result += getWorkspaceData(w.get(), format);
|
result += getWorkspaceData(w.get(), format);
|
||||||
|
@ -314,9 +323,9 @@ std::string workspacesRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string workspaceRulesRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
std::string workspaceRulesRequest(eHyprCtlOutputFormat format, std::string request) {
|
||||||
std::string result = "";
|
std::string result = "";
|
||||||
if (format == HyprCtl::FORMAT_JSON) {
|
if (format == eHyprCtlOutputFormat::FORMAT_JSON) {
|
||||||
result += "[";
|
result += "[";
|
||||||
for (auto& r : g_pConfigManager->getAllWorkspaceRules()) {
|
for (auto& r : g_pConfigManager->getAllWorkspaceRules()) {
|
||||||
result += getWorkspaceRuleData(r, format);
|
result += getWorkspaceRuleData(r, format);
|
||||||
|
@ -334,24 +343,24 @@ std::string workspaceRulesRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string activeWindowRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
std::string activeWindowRequest(eHyprCtlOutputFormat format, std::string request) {
|
||||||
const auto PWINDOW = g_pCompositor->m_pLastWindow;
|
const auto PWINDOW = g_pCompositor->m_pLastWindow;
|
||||||
|
|
||||||
if (!g_pCompositor->windowValidMapped(PWINDOW))
|
if (!g_pCompositor->windowValidMapped(PWINDOW))
|
||||||
return format == HyprCtl::FORMAT_JSON ? "{}" : "Invalid";
|
return format == eHyprCtlOutputFormat::FORMAT_JSON ? "{}" : "Invalid";
|
||||||
|
|
||||||
auto result = getWindowData(PWINDOW, format);
|
auto result = getWindowData(PWINDOW, format);
|
||||||
|
|
||||||
if (format == HyprCtl::FORMAT_JSON)
|
if (format == eHyprCtlOutputFormat::FORMAT_JSON)
|
||||||
result.pop_back();
|
result.pop_back();
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string layersRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
std::string layersRequest(eHyprCtlOutputFormat format, std::string request) {
|
||||||
std::string result = "";
|
std::string result = "";
|
||||||
|
|
||||||
if (format == HyprCtl::FORMAT_JSON) {
|
if (format == eHyprCtlOutputFormat::FORMAT_JSON) {
|
||||||
result += "{\n";
|
result += "{\n";
|
||||||
|
|
||||||
for (auto& mon : g_pCompositor->m_vMonitors) {
|
for (auto& mon : g_pCompositor->m_vMonitors) {
|
||||||
|
@ -422,9 +431,9 @@ std::string layersRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string layoutsRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
std::string layoutsRequest(eHyprCtlOutputFormat format, std::string request) {
|
||||||
std::string result = "";
|
std::string result = "";
|
||||||
if (format == HyprCtl::FORMAT_JSON) {
|
if (format == eHyprCtlOutputFormat::FORMAT_JSON) {
|
||||||
result += "[";
|
result += "[";
|
||||||
|
|
||||||
for (auto& m : g_pLayoutManager->getAllLayoutNames()) {
|
for (auto& m : g_pLayoutManager->getAllLayoutNames()) {
|
||||||
|
@ -444,10 +453,10 @@ std::string layoutsRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string devicesRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
std::string devicesRequest(eHyprCtlOutputFormat format, std::string request) {
|
||||||
std::string result = "";
|
std::string result = "";
|
||||||
|
|
||||||
if (format == HyprCtl::FORMAT_JSON) {
|
if (format == eHyprCtlOutputFormat::FORMAT_JSON) {
|
||||||
result += "{\n";
|
result += "{\n";
|
||||||
result += "\"mice\": [\n";
|
result += "\"mice\": [\n";
|
||||||
|
|
||||||
|
@ -603,9 +612,9 @@ std::string devicesRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string animationsRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
std::string animationsRequest(eHyprCtlOutputFormat format, std::string request) {
|
||||||
std::string ret = "";
|
std::string ret = "";
|
||||||
if (format == HyprCtl::eHyprCtlOutputFormat::FORMAT_NORMAL) {
|
if (format == eHyprCtlOutputFormat::FORMAT_NORMAL) {
|
||||||
ret += "animations:\n";
|
ret += "animations:\n";
|
||||||
|
|
||||||
for (auto& ac : g_pConfigManager->getAnimationConfig()) {
|
for (auto& ac : g_pConfigManager->getAnimationConfig()) {
|
||||||
|
@ -656,10 +665,10 @@ std::string animationsRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string rollinglogRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
std::string rollinglogRequest(eHyprCtlOutputFormat format, std::string request) {
|
||||||
std::string result = "";
|
std::string result = "";
|
||||||
|
|
||||||
if (format == HyprCtl::FORMAT_JSON) {
|
if (format == eHyprCtlOutputFormat::FORMAT_JSON) {
|
||||||
result += "[\n\"log\":\"";
|
result += "[\n\"log\":\"";
|
||||||
result += escapeJSONStrings(Debug::rollingLog);
|
result += escapeJSONStrings(Debug::rollingLog);
|
||||||
result += "\"]";
|
result += "\"]";
|
||||||
|
@ -670,10 +679,10 @@ std::string rollinglogRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string globalShortcutsRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
std::string globalShortcutsRequest(eHyprCtlOutputFormat format, std::string request) {
|
||||||
std::string ret = "";
|
std::string ret = "";
|
||||||
const auto SHORTCUTS = g_pProtocolManager->m_pGlobalShortcutsProtocolManager->getAllShortcuts();
|
const auto SHORTCUTS = g_pProtocolManager->m_pGlobalShortcutsProtocolManager->getAllShortcuts();
|
||||||
if (format == HyprCtl::eHyprCtlOutputFormat::FORMAT_NORMAL) {
|
if (format == eHyprCtlOutputFormat::FORMAT_NORMAL) {
|
||||||
for (auto& sh : SHORTCUTS)
|
for (auto& sh : SHORTCUTS)
|
||||||
ret += std::format("{}:{} -> {}\n", sh.appid, sh.id, sh.description);
|
ret += std::format("{}:{} -> {}\n", sh.appid, sh.id, sh.description);
|
||||||
} else {
|
} else {
|
||||||
|
@ -693,9 +702,9 @@ std::string globalShortcutsRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string bindsRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
std::string bindsRequest(eHyprCtlOutputFormat format, std::string request) {
|
||||||
std::string ret = "";
|
std::string ret = "";
|
||||||
if (format == HyprCtl::eHyprCtlOutputFormat::FORMAT_NORMAL) {
|
if (format == eHyprCtlOutputFormat::FORMAT_NORMAL) {
|
||||||
for (auto& kb : g_pKeybindManager->m_lKeybinds) {
|
for (auto& kb : g_pKeybindManager->m_lKeybinds) {
|
||||||
ret += "bind";
|
ret += "bind";
|
||||||
if (kb.locked)
|
if (kb.locked)
|
||||||
|
@ -741,12 +750,12 @@ std::string bindsRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string versionRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
std::string versionRequest(eHyprCtlOutputFormat format, std::string request) {
|
||||||
|
|
||||||
auto commitMsg = removeBeginEndSpacesTabs(GIT_COMMIT_MESSAGE);
|
auto commitMsg = removeBeginEndSpacesTabs(GIT_COMMIT_MESSAGE);
|
||||||
std::replace(commitMsg.begin(), commitMsg.end(), '#', ' ');
|
std::replace(commitMsg.begin(), commitMsg.end(), '#', ' ');
|
||||||
|
|
||||||
if (format == HyprCtl::eHyprCtlOutputFormat::FORMAT_NORMAL) {
|
if (format == eHyprCtlOutputFormat::FORMAT_NORMAL) {
|
||||||
std::string result = "Hyprland, built from branch " + std::string(GIT_BRANCH) + " at commit " + GIT_COMMIT_HASH + " " + GIT_DIRTY + " (" + commitMsg +
|
std::string result = "Hyprland, built from branch " + std::string(GIT_BRANCH) + " at commit " + GIT_COMMIT_HASH + " " + GIT_DIRTY + " (" + commitMsg +
|
||||||
").\nDate: " + GIT_COMMIT_DATE + "\nTag: " + GIT_TAG + "\n\nflags: (if any)\n";
|
").\nDate: " + GIT_COMMIT_DATE + "\nTag: " + GIT_TAG + "\n\nflags: (if any)\n";
|
||||||
|
|
||||||
|
@ -793,7 +802,40 @@ std::string versionRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||||
return ""; // make the compiler happy
|
return ""; // make the compiler happy
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string dispatchRequest(std::string in) {
|
std::string systemInfoRequest(eHyprCtlOutputFormat format, std::string request) {
|
||||||
|
std::string result = versionRequest(eHyprCtlOutputFormat::FORMAT_NORMAL, "");
|
||||||
|
|
||||||
|
result += "\n\nSystem Information:\n";
|
||||||
|
|
||||||
|
struct utsname unameInfo;
|
||||||
|
|
||||||
|
uname(&unameInfo);
|
||||||
|
|
||||||
|
result += "System name: " + std::string{unameInfo.sysname} + "\n";
|
||||||
|
result += "Node name: " + std::string{unameInfo.nodename} + "\n";
|
||||||
|
result += "Release: " + std::string{unameInfo.release} + "\n";
|
||||||
|
result += "Version: " + std::string{unameInfo.version} + "\n";
|
||||||
|
|
||||||
|
result += "\n\n";
|
||||||
|
|
||||||
|
#if defined(__DragonFly__) || defined(__FreeBSD__)
|
||||||
|
const std::string GPUINFO = execAndGet("pciconf -lv | fgrep -A4 vga");
|
||||||
|
#else
|
||||||
|
const std::string GPUINFO = execAndGet("lspci -vnn | grep VGA");
|
||||||
|
#endif
|
||||||
|
result += "GPU information: \n" + GPUINFO + "\n\n";
|
||||||
|
|
||||||
|
result += "os-release: " + execAndGet("cat /etc/os-release") + "\n\n";
|
||||||
|
|
||||||
|
result += "plugins:\n";
|
||||||
|
for (auto& pl : g_pPluginSystem->getAllPlugins()) {
|
||||||
|
result += std::format(" {} by {} ver {}\n", pl->name, pl->author, pl->version);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string dispatchRequest(eHyprCtlOutputFormat format, std::string in) {
|
||||||
// get rid of the dispatch keyword
|
// get rid of the dispatch keyword
|
||||||
in = in.substr(in.find_first_of(' ') + 1);
|
in = in.substr(in.find_first_of(' ') + 1);
|
||||||
|
|
||||||
|
@ -814,7 +856,7 @@ std::string dispatchRequest(std::string in) {
|
||||||
return "ok";
|
return "ok";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string dispatchKeyword(std::string in) {
|
std::string dispatchKeyword(eHyprCtlOutputFormat format, std::string in) {
|
||||||
// get rid of the keyword keyword
|
// get rid of the keyword keyword
|
||||||
in = in.substr(in.find_first_of(' ') + 1);
|
in = in.substr(in.find_first_of(' ') + 1);
|
||||||
|
|
||||||
|
@ -822,32 +864,35 @@ std::string dispatchKeyword(std::string in) {
|
||||||
|
|
||||||
const auto VALUE = in.substr(in.find_first_of(' ') + 1);
|
const auto VALUE = in.substr(in.find_first_of(' ') + 1);
|
||||||
|
|
||||||
std::string retval = g_pConfigManager->parseKeyword(COMMAND, VALUE, true);
|
std::string retval = g_pConfigManager->parseKeyword(COMMAND, VALUE);
|
||||||
|
|
||||||
if (COMMAND == "monitor")
|
// 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")
|
||||||
g_pConfigManager->m_bWantsMonitorReload = true; // for monitor keywords
|
g_pConfigManager->m_bWantsMonitorReload = true; // for monitor keywords
|
||||||
|
|
||||||
if (COMMAND.contains("input") || COMMAND.contains("device:")) {
|
if (COMMAND.contains("input") || COMMAND.contains("device") || COMMAND == "source") {
|
||||||
g_pInputManager->setKeyboardLayout(); // update kb layout
|
g_pInputManager->setKeyboardLayout(); // update kb layout
|
||||||
g_pInputManager->setPointerConfigs(); // update mouse cfgs
|
g_pInputManager->setPointerConfigs(); // update mouse cfgs
|
||||||
g_pInputManager->setTouchDeviceConfigs(); // update touch device cfgs
|
g_pInputManager->setTouchDeviceConfigs(); // update touch device cfgs
|
||||||
g_pInputManager->setTabletConfigs(); // update tablets
|
g_pInputManager->setTabletConfigs(); // update tablets
|
||||||
}
|
}
|
||||||
|
|
||||||
if (COMMAND.contains("general:layout"))
|
static auto* const PLAYOUT = (Hyprlang::STRING const*)g_pConfigManager->getConfigValuePtr("general:layout");
|
||||||
g_pLayoutManager->switchToLayout(g_pConfigManager->getString("general:layout")); // update layout
|
|
||||||
|
|
||||||
if (COMMAND.contains("decoration:screen_shader"))
|
if (COMMAND.contains("general:layout"))
|
||||||
|
g_pLayoutManager->switchToLayout(*PLAYOUT); // update layout
|
||||||
|
|
||||||
|
if (COMMAND.contains("decoration:screen_shader") || COMMAND == "source")
|
||||||
g_pHyprOpenGL->m_bReloadScreenShader = true;
|
g_pHyprOpenGL->m_bReloadScreenShader = true;
|
||||||
|
|
||||||
if (COMMAND.contains("blur")) {
|
if (COMMAND.contains("blur") || COMMAND == "source") {
|
||||||
for (auto& [m, rd] : g_pHyprOpenGL->m_mMonitorRenderResources) {
|
for (auto& [m, rd] : g_pHyprOpenGL->m_mMonitorRenderResources) {
|
||||||
rd.blurFBDirty = true;
|
rd.blurFBDirty = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// decorations will probably need a repaint
|
// decorations will probably need a repaint
|
||||||
if (COMMAND.contains("decoration:") || COMMAND.contains("border") || COMMAND == "workspace" || COMMAND.contains("cursor_zoom_factor")) {
|
if (COMMAND.contains("decoration:") || COMMAND.contains("border") || COMMAND == "workspace" || COMMAND.contains("cursor_zoom_factor") || COMMAND == "source") {
|
||||||
for (auto& m : g_pCompositor->m_vMonitors) {
|
for (auto& m : g_pCompositor->m_vMonitors) {
|
||||||
g_pHyprRenderer->damageMonitor(m.get());
|
g_pHyprRenderer->damageMonitor(m.get());
|
||||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m->ID);
|
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m->ID);
|
||||||
|
@ -862,7 +907,7 @@ std::string dispatchKeyword(std::string in) {
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string reloadRequest(const std::string& request) {
|
std::string reloadRequest(eHyprCtlOutputFormat format, std::string request) {
|
||||||
|
|
||||||
const auto REQMODE = request.substr(request.find_last_of(' ') + 1);
|
const auto REQMODE = request.substr(request.find_last_of(' ') + 1);
|
||||||
|
|
||||||
|
@ -877,20 +922,20 @@ std::string reloadRequest(const std::string& request) {
|
||||||
return "ok";
|
return "ok";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string killRequest() {
|
std::string killRequest(eHyprCtlOutputFormat format, std::string request) {
|
||||||
g_pInputManager->setClickMode(CLICKMODE_KILL);
|
g_pInputManager->setClickMode(CLICKMODE_KILL);
|
||||||
|
|
||||||
return "ok";
|
return "ok";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string splashRequest() {
|
std::string splashRequest(eHyprCtlOutputFormat format, std::string request) {
|
||||||
return g_pCompositor->m_szCurrentSplash;
|
return g_pCompositor->m_szCurrentSplash;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string cursorPosRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
std::string cursorPosRequest(eHyprCtlOutputFormat format, std::string request) {
|
||||||
const auto CURSORPOS = g_pInputManager->getMouseCoordsInternal().floor();
|
const auto CURSORPOS = g_pInputManager->getMouseCoordsInternal().floor();
|
||||||
|
|
||||||
if (format == HyprCtl::FORMAT_NORMAL) {
|
if (format == eHyprCtlOutputFormat::FORMAT_NORMAL) {
|
||||||
return std::format("{}, {}", (int)CURSORPOS.x, (int)CURSORPOS.y);
|
return std::format("{}, {}", (int)CURSORPOS.x, (int)CURSORPOS.y);
|
||||||
} else {
|
} else {
|
||||||
return std::format(R"#(
|
return std::format(R"#(
|
||||||
|
@ -905,9 +950,7 @@ std::string cursorPosRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||||
return "error";
|
return "error";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string getReply(std::string);
|
std::string dispatchBatch(eHyprCtlOutputFormat format, std::string request) {
|
||||||
|
|
||||||
std::string dispatchBatch(std::string request) {
|
|
||||||
// split by ;
|
// split by ;
|
||||||
|
|
||||||
request = request.substr(9);
|
request = request.substr(9);
|
||||||
|
@ -930,8 +973,8 @@ std::string dispatchBatch(std::string request) {
|
||||||
|
|
||||||
nextItem();
|
nextItem();
|
||||||
|
|
||||||
while (curitem != "") {
|
while (curitem != "" || request != "") {
|
||||||
reply += getReply(curitem);
|
reply += g_pHyprCtl->getReply(curitem);
|
||||||
|
|
||||||
nextItem();
|
nextItem();
|
||||||
}
|
}
|
||||||
|
@ -939,7 +982,7 @@ std::string dispatchBatch(std::string request) {
|
||||||
return reply;
|
return reply;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string dispatchSetCursor(std::string request) {
|
std::string dispatchSetCursor(eHyprCtlOutputFormat format, std::string request) {
|
||||||
CVarList vars(request, 0, ' ');
|
CVarList vars(request, 0, ' ');
|
||||||
|
|
||||||
const auto SIZESTR = vars[vars.size() - 1];
|
const auto SIZESTR = vars[vars.size() - 1];
|
||||||
|
@ -971,7 +1014,7 @@ std::string dispatchSetCursor(std::string request) {
|
||||||
return "ok";
|
return "ok";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string switchXKBLayoutRequest(const std::string& request) {
|
std::string switchXKBLayoutRequest(eHyprCtlOutputFormat format, std::string request) {
|
||||||
CVarList vars(request, 0, ' ');
|
CVarList vars(request, 0, ' ');
|
||||||
|
|
||||||
const auto KB = vars[1];
|
const auto KB = vars[1];
|
||||||
|
@ -1017,7 +1060,7 @@ std::string switchXKBLayoutRequest(const std::string& request) {
|
||||||
return "ok";
|
return "ok";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string dispatchSeterror(std::string request) {
|
std::string dispatchSeterror(eHyprCtlOutputFormat format, std::string request) {
|
||||||
CVarList vars(request, 0, ' ');
|
CVarList vars(request, 0, ' ');
|
||||||
|
|
||||||
std::string errorMessage = "";
|
std::string errorMessage = "";
|
||||||
|
@ -1046,13 +1089,14 @@ std::string dispatchSeterror(std::string request) {
|
||||||
return "ok";
|
return "ok";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string dispatchSetProp(std::string request) {
|
std::string dispatchSetProp(eHyprCtlOutputFormat format, std::string request) {
|
||||||
CVarList vars(request, 0, ' ');
|
CVarList vars(request, 0, ' ');
|
||||||
|
|
||||||
if (vars.size() < 4)
|
if (vars.size() < 4)
|
||||||
return "not enough args";
|
return "not enough args";
|
||||||
|
|
||||||
const auto PWINDOW = g_pCompositor->getWindowByRegex(vars[1]);
|
const auto PLASTWINDOW = g_pCompositor->m_pLastWindow;
|
||||||
|
const auto PWINDOW = g_pCompositor->getWindowByRegex(vars[1]);
|
||||||
|
|
||||||
if (!PWINDOW)
|
if (!PWINDOW)
|
||||||
return "window not found";
|
return "window not found";
|
||||||
|
@ -1060,6 +1104,8 @@ std::string dispatchSetProp(std::string request) {
|
||||||
const auto PROP = vars[2];
|
const auto PROP = vars[2];
|
||||||
const auto VAL = vars[3];
|
const auto VAL = vars[3];
|
||||||
|
|
||||||
|
auto noFocus = PWINDOW->m_sAdditionalConfigData.noFocus;
|
||||||
|
|
||||||
bool lock = false;
|
bool lock = false;
|
||||||
|
|
||||||
if (vars.size() > 4) {
|
if (vars.size() > 4) {
|
||||||
|
@ -1089,6 +1135,8 @@ std::string dispatchSetProp(std::string request) {
|
||||||
PWINDOW->m_sAdditionalConfigData.forceNoShadow.forceSetIgnoreLocked(configStringToInt(VAL), lock);
|
PWINDOW->m_sAdditionalConfigData.forceNoShadow.forceSetIgnoreLocked(configStringToInt(VAL), lock);
|
||||||
} else if (PROP == "forcenodim") {
|
} else if (PROP == "forcenodim") {
|
||||||
PWINDOW->m_sAdditionalConfigData.forceNoDim.forceSetIgnoreLocked(configStringToInt(VAL), lock);
|
PWINDOW->m_sAdditionalConfigData.forceNoDim.forceSetIgnoreLocked(configStringToInt(VAL), lock);
|
||||||
|
} else if (PROP == "nofocus") {
|
||||||
|
PWINDOW->m_sAdditionalConfigData.noFocus.forceSetIgnoreLocked(configStringToInt(VAL), lock);
|
||||||
} else if (PROP == "windowdancecompat") {
|
} else if (PROP == "windowdancecompat") {
|
||||||
PWINDOW->m_sAdditionalConfigData.windowDanceCompat.forceSetIgnoreLocked(configStringToInt(VAL), lock);
|
PWINDOW->m_sAdditionalConfigData.windowDanceCompat.forceSetIgnoreLocked(configStringToInt(VAL), lock);
|
||||||
} else if (PROP == "nomaxsize") {
|
} else if (PROP == "nomaxsize") {
|
||||||
|
@ -1124,13 +1172,19 @@ std::string dispatchSetProp(std::string request) {
|
||||||
|
|
||||||
g_pCompositor->updateAllWindowsAnimatedDecorationValues();
|
g_pCompositor->updateAllWindowsAnimatedDecorationValues();
|
||||||
|
|
||||||
|
if (!(PWINDOW->m_sAdditionalConfigData.noFocus.toUnderlying() == noFocus.toUnderlying())) {
|
||||||
|
g_pCompositor->focusWindow(nullptr);
|
||||||
|
g_pCompositor->focusWindow(PWINDOW);
|
||||||
|
g_pCompositor->focusWindow(PLASTWINDOW);
|
||||||
|
}
|
||||||
|
|
||||||
for (auto& m : g_pCompositor->m_vMonitors)
|
for (auto& m : g_pCompositor->m_vMonitors)
|
||||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m->ID);
|
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m->ID);
|
||||||
|
|
||||||
return "ok";
|
return "ok";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string dispatchGetOption(std::string request, HyprCtl::eHyprCtlOutputFormat format) {
|
std::string dispatchGetOption(eHyprCtlOutputFormat format, std::string request) {
|
||||||
std::string curitem = "";
|
std::string curitem = "";
|
||||||
|
|
||||||
auto nextItem = [&]() {
|
auto nextItem = [&]() {
|
||||||
|
@ -1150,31 +1204,43 @@ std::string dispatchGetOption(std::string request, HyprCtl::eHyprCtlOutputFormat
|
||||||
nextItem();
|
nextItem();
|
||||||
nextItem();
|
nextItem();
|
||||||
|
|
||||||
const auto PCFGOPT = g_pConfigManager->getConfigValuePtrSafe(curitem);
|
const auto VAR = g_pConfigManager->getHyprlangConfigValuePtr(curitem);
|
||||||
|
|
||||||
if (!PCFGOPT)
|
if (!VAR)
|
||||||
return "no such option";
|
return "no such option";
|
||||||
|
|
||||||
if (format == HyprCtl::eHyprCtlOutputFormat::FORMAT_NORMAL)
|
const auto VAL = VAR->getValue();
|
||||||
return std::format("option {}\n\tint: {}\n\tfloat: {:.5f}\n\tstr: \"{}\"\n\tdata: {:x}\n\tset: {}", curitem, PCFGOPT->intValue, PCFGOPT->floatValue, PCFGOPT->strValue,
|
const auto TYPE = std::type_index(VAL.type());
|
||||||
(uintptr_t)PCFGOPT->data.get(), PCFGOPT->set);
|
|
||||||
else {
|
if (format == FORMAT_NORMAL) {
|
||||||
return std::format(
|
if (TYPE == typeid(Hyprlang::INT))
|
||||||
R"#(
|
return std::format("int: {}\nset: {}", std::any_cast<Hyprlang::INT>(VAL), VAR->m_bSetByUser);
|
||||||
{{
|
else if (TYPE == typeid(Hyprlang::FLOAT))
|
||||||
"option": "{}",
|
return std::format("float: {:2f}\nset: {}", std::any_cast<Hyprlang::FLOAT>(VAL), VAR->m_bSetByUser);
|
||||||
"int": {},
|
else if (TYPE == typeid(Hyprlang::VEC2))
|
||||||
"float": {:.5f},
|
return std::format("vec2: [{}, {}]\nset: {}", std::any_cast<Hyprlang::VEC2>(VAL).x, std::any_cast<Hyprlang::VEC2>(VAL).y, VAR->m_bSetByUser);
|
||||||
"str": "{}",
|
else if (TYPE == typeid(Hyprlang::STRING))
|
||||||
"data": "0x{:x}",
|
return std::format("str: {}\nset: {}", std::any_cast<Hyprlang::STRING>(VAL), VAR->m_bSetByUser);
|
||||||
"set": {}
|
else if (TYPE == typeid(Hyprlang::CUSTOMTYPE*))
|
||||||
}}
|
return std::format("custom type at: {:x}\nset: {}", (uintptr_t)std::any_cast<Hyprlang::CUSTOMTYPE*>(VAL), VAR->m_bSetByUser);
|
||||||
)#",
|
} else {
|
||||||
curitem, PCFGOPT->intValue, PCFGOPT->floatValue, PCFGOPT->strValue, (uintptr_t)PCFGOPT->data.get(), PCFGOPT->set);
|
if (TYPE == typeid(Hyprlang::INT))
|
||||||
|
return std::format("{{\"option\": \"{}\", \"int\": {}, \"set\": {} }}", curitem, std::any_cast<Hyprlang::INT>(VAL), VAR->m_bSetByUser);
|
||||||
|
else if (TYPE == typeid(Hyprlang::FLOAT))
|
||||||
|
return std::format("{{\"option\": \"{}\", \"float\": {:2f}, \"set\": {} }}", curitem, std::any_cast<Hyprlang::FLOAT>(VAL), VAR->m_bSetByUser);
|
||||||
|
else if (TYPE == typeid(Hyprlang::VEC2))
|
||||||
|
return std::format("{{\"option\": \"{}\", \"vec2\": [{},{}], \"set\": {} }}", curitem, std::any_cast<Hyprlang::VEC2>(VAL).x, std::any_cast<Hyprlang::VEC2>(VAL).y,
|
||||||
|
VAR->m_bSetByUser);
|
||||||
|
else if (TYPE == typeid(Hyprlang::STRING))
|
||||||
|
return std::format("{{\"option\": \"{}\", \"str\": \"{}\", \"set\": {} }}", curitem, escapeJSONStrings(std::any_cast<Hyprlang::STRING>(VAL)), VAR->m_bSetByUser);
|
||||||
|
else if (TYPE == typeid(Hyprlang::CUSTOMTYPE*))
|
||||||
|
return std::format("{{\"option\": \"{}\", \"custom\": \"{:x}\", \"set\": {} }}", curitem, (uintptr_t)std::any_cast<Hyprlang::CUSTOMTYPE*>(VAL), VAR->m_bSetByUser);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return "invalid type (internal error)";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string decorationRequest(std::string request, HyprCtl::eHyprCtlOutputFormat format) {
|
std::string decorationRequest(eHyprCtlOutputFormat format, std::string request) {
|
||||||
CVarList vars(request, 0, ' ');
|
CVarList vars(request, 0, ' ');
|
||||||
const auto PWINDOW = g_pCompositor->getWindowByRegex(vars[1]);
|
const auto PWINDOW = g_pCompositor->getWindowByRegex(vars[1]);
|
||||||
|
|
||||||
|
@ -1182,7 +1248,7 @@ std::string decorationRequest(std::string request, HyprCtl::eHyprCtlOutputFormat
|
||||||
return "none";
|
return "none";
|
||||||
|
|
||||||
std::string result = "";
|
std::string result = "";
|
||||||
if (format == HyprCtl::FORMAT_JSON) {
|
if (format == eHyprCtlOutputFormat::FORMAT_JSON) {
|
||||||
result += "[";
|
result += "[";
|
||||||
for (auto& wd : PWINDOW->m_dWindowDecorations) {
|
for (auto& wd : PWINDOW->m_dWindowDecorations) {
|
||||||
result += "{\n\"decorationName\": \"" + wd->getDisplayName() + "\",\n\"priority\": " + std::to_string(wd->getPositioningInfo().priority) + "\n},";
|
result += "{\n\"decorationName\": \"" + wd->getDisplayName() + "\",\n\"priority\": " + std::to_string(wd->getPositioningInfo().priority) + "\n},";
|
||||||
|
@ -1231,7 +1297,7 @@ void createOutputIter(wlr_backend* backend, void* data) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string dispatchOutput(std::string request) {
|
std::string dispatchOutput(eHyprCtlOutputFormat format, std::string request) {
|
||||||
std::string curitem = "";
|
std::string curitem = "";
|
||||||
|
|
||||||
auto nextItem = [&]() {
|
auto nextItem = [&]() {
|
||||||
|
@ -1280,7 +1346,7 @@ std::string dispatchOutput(std::string request) {
|
||||||
return "ok";
|
return "ok";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string dispatchPlugin(std::string request) {
|
std::string dispatchPlugin(eHyprCtlOutputFormat format, std::string request) {
|
||||||
CVarList vars(request, 0, ' ');
|
CVarList vars(request, 0, ' ');
|
||||||
|
|
||||||
if (vars.size() < 2)
|
if (vars.size() < 2)
|
||||||
|
@ -1323,7 +1389,7 @@ std::string dispatchPlugin(std::string request) {
|
||||||
return "ok";
|
return "ok";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string dispatchNotify(std::string request) {
|
std::string dispatchNotify(eHyprCtlOutputFormat format, std::string request) {
|
||||||
CVarList vars(request, 0, ' ');
|
CVarList vars(request, 0, ' ');
|
||||||
|
|
||||||
if (vars.size() < 5)
|
if (vars.size() < 5)
|
||||||
|
@ -1364,92 +1430,137 @@ std::string dispatchNotify(std::string request) {
|
||||||
return "ok";
|
return "ok";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string getReply(std::string request) {
|
CHyprCtl::CHyprCtl() {
|
||||||
auto format = HyprCtl::FORMAT_NORMAL;
|
registerCommand(SHyprCtlCommand{"workspaces", true, workspacesRequest});
|
||||||
|
registerCommand(SHyprCtlCommand{"workspacerules", true, workspaceRulesRequest});
|
||||||
|
registerCommand(SHyprCtlCommand{"activeworkspace", true, activeWorkspaceRequest});
|
||||||
|
registerCommand(SHyprCtlCommand{"clients", true, clientsRequest});
|
||||||
|
registerCommand(SHyprCtlCommand{"kill", true, killRequest});
|
||||||
|
registerCommand(SHyprCtlCommand{"activewindow", true, activeWindowRequest});
|
||||||
|
registerCommand(SHyprCtlCommand{"layers", true, layersRequest});
|
||||||
|
registerCommand(SHyprCtlCommand{"version", true, versionRequest});
|
||||||
|
registerCommand(SHyprCtlCommand{"devices", true, devicesRequest});
|
||||||
|
registerCommand(SHyprCtlCommand{"splash", true, splashRequest});
|
||||||
|
registerCommand(SHyprCtlCommand{"cursorpos", true, cursorPosRequest});
|
||||||
|
registerCommand(SHyprCtlCommand{"binds", true, bindsRequest});
|
||||||
|
registerCommand(SHyprCtlCommand{"globalshortcuts", true, globalShortcutsRequest});
|
||||||
|
registerCommand(SHyprCtlCommand{"systeminfo", true, systemInfoRequest});
|
||||||
|
registerCommand(SHyprCtlCommand{"animations", true, animationsRequest});
|
||||||
|
registerCommand(SHyprCtlCommand{"rollinglog", true, rollinglogRequest});
|
||||||
|
registerCommand(SHyprCtlCommand{"layouts", true, layoutsRequest});
|
||||||
|
|
||||||
|
registerCommand(SHyprCtlCommand{"monitors", false, monitorsRequest});
|
||||||
|
registerCommand(SHyprCtlCommand{"reload", false, reloadRequest});
|
||||||
|
registerCommand(SHyprCtlCommand{"plugin", false, dispatchPlugin});
|
||||||
|
registerCommand(SHyprCtlCommand{"notify", false, dispatchNotify});
|
||||||
|
registerCommand(SHyprCtlCommand{"setprop", false, dispatchSetProp});
|
||||||
|
registerCommand(SHyprCtlCommand{"seterror", false, dispatchSeterror});
|
||||||
|
registerCommand(SHyprCtlCommand{"switchxkblayout", false, switchXKBLayoutRequest});
|
||||||
|
registerCommand(SHyprCtlCommand{"output", false, dispatchOutput});
|
||||||
|
registerCommand(SHyprCtlCommand{"dispatch", false, dispatchRequest});
|
||||||
|
registerCommand(SHyprCtlCommand{"keyword", false, dispatchKeyword});
|
||||||
|
registerCommand(SHyprCtlCommand{"setcursor", false, dispatchSetCursor});
|
||||||
|
registerCommand(SHyprCtlCommand{"getoption", false, dispatchGetOption});
|
||||||
|
registerCommand(SHyprCtlCommand{"decorations", false, decorationRequest});
|
||||||
|
registerCommand(SHyprCtlCommand{"[[BATCH]]", false, dispatchBatch});
|
||||||
|
|
||||||
|
startHyprCtlSocket();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<SHyprCtlCommand> CHyprCtl::registerCommand(SHyprCtlCommand cmd) {
|
||||||
|
return m_vCommands.emplace_back(std::make_shared<SHyprCtlCommand>(cmd));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CHyprCtl::unregisterCommand(const std::shared_ptr<SHyprCtlCommand>& cmd) {
|
||||||
|
std::erase(m_vCommands, cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string CHyprCtl::getReply(std::string request) {
|
||||||
|
auto format = eHyprCtlOutputFormat::FORMAT_NORMAL;
|
||||||
|
bool reloadAll = false;
|
||||||
|
|
||||||
// process flags for non-batch requests
|
// process flags for non-batch requests
|
||||||
if (!request.contains("[[BATCH]]") && request.contains("/")) {
|
if (!request.starts_with("[[BATCH]]") && request.contains("/")) {
|
||||||
long unsigned int sepIndex = 0;
|
long unsigned int sepIndex = 0;
|
||||||
for (const auto& c : request) {
|
for (const auto& c : request) {
|
||||||
if (c == '/') { // stop at separator
|
if (c == '/') { // stop at separator
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// after whitespace assume the first word as a keyword,
|
||||||
|
// so its value can have slashes (e.g., a path)
|
||||||
|
if (c == ' ') {
|
||||||
|
sepIndex = request.size();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
sepIndex++;
|
sepIndex++;
|
||||||
|
|
||||||
if (c == 'j')
|
if (c == 'j')
|
||||||
format = HyprCtl::FORMAT_JSON;
|
format = eHyprCtlOutputFormat::FORMAT_JSON;
|
||||||
|
if (c == 'r')
|
||||||
|
reloadAll = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sepIndex < request.size())
|
if (sepIndex < request.size())
|
||||||
request = request.substr(sepIndex + 1); // remove flags and separator so we can compare the rest of the string
|
request = request.substr(sepIndex + 1); // remove flags and separator so we can compare the rest of the string
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request.starts_with("monitors"))
|
std::string result = "";
|
||||||
return monitorsRequest(request, format);
|
|
||||||
else if (request == "workspaces")
|
|
||||||
return workspacesRequest(format);
|
|
||||||
else if (request == "workspacerules")
|
|
||||||
return workspaceRulesRequest(format);
|
|
||||||
else if (request == "activeworkspace")
|
|
||||||
return activeWorkspaceRequest(format);
|
|
||||||
else if (request == "clients")
|
|
||||||
return clientsRequest(format);
|
|
||||||
else if (request == "kill")
|
|
||||||
return killRequest();
|
|
||||||
else if (request == "activewindow")
|
|
||||||
return activeWindowRequest(format);
|
|
||||||
else if (request == "layers")
|
|
||||||
return layersRequest(format);
|
|
||||||
else if (request == "version")
|
|
||||||
return versionRequest(format);
|
|
||||||
else if (request.starts_with("reload"))
|
|
||||||
return reloadRequest(request);
|
|
||||||
else if (request == "devices")
|
|
||||||
return devicesRequest(format);
|
|
||||||
else if (request == "splash")
|
|
||||||
return splashRequest();
|
|
||||||
else if (request == "cursorpos")
|
|
||||||
return cursorPosRequest(format);
|
|
||||||
else if (request == "binds")
|
|
||||||
return bindsRequest(format);
|
|
||||||
else if (request == "globalshortcuts")
|
|
||||||
return globalShortcutsRequest(format);
|
|
||||||
else if (request == "animations")
|
|
||||||
return animationsRequest(format);
|
|
||||||
else if (request == "rollinglog")
|
|
||||||
return rollinglogRequest(format);
|
|
||||||
else if (request == "layouts")
|
|
||||||
return layoutsRequest(format);
|
|
||||||
else if (request.starts_with("plugin"))
|
|
||||||
return dispatchPlugin(request);
|
|
||||||
else if (request.starts_with("notify"))
|
|
||||||
return dispatchNotify(request);
|
|
||||||
else if (request.starts_with("setprop"))
|
|
||||||
return dispatchSetProp(request);
|
|
||||||
else if (request.starts_with("seterror"))
|
|
||||||
return dispatchSeterror(request);
|
|
||||||
else if (request.starts_with("switchxkblayout"))
|
|
||||||
return switchXKBLayoutRequest(request);
|
|
||||||
else if (request.starts_with("output"))
|
|
||||||
return dispatchOutput(request);
|
|
||||||
else if (request.starts_with("dispatch"))
|
|
||||||
return dispatchRequest(request);
|
|
||||||
else if (request.starts_with("keyword"))
|
|
||||||
return dispatchKeyword(request);
|
|
||||||
else if (request.starts_with("setcursor"))
|
|
||||||
return dispatchSetCursor(request);
|
|
||||||
else if (request.starts_with("getoption"))
|
|
||||||
return dispatchGetOption(request, format);
|
|
||||||
else if (request.starts_with("decorations"))
|
|
||||||
return decorationRequest(request, format);
|
|
||||||
else if (request.starts_with("[[BATCH]]"))
|
|
||||||
return dispatchBatch(request);
|
|
||||||
|
|
||||||
return "unknown request";
|
// parse exact cmds first, then non-exact.
|
||||||
|
for (auto& cmd : m_vCommands) {
|
||||||
|
if (!cmd->exact)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (cmd->name == request) {
|
||||||
|
result = cmd->fn(format, request);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.empty())
|
||||||
|
for (auto& cmd : m_vCommands) {
|
||||||
|
if (cmd->exact)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (request.starts_with(cmd->name)) {
|
||||||
|
result = cmd->fn(format, request);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.empty())
|
||||||
|
return "unknown request";
|
||||||
|
|
||||||
|
if (reloadAll) {
|
||||||
|
g_pConfigManager->m_bWantsMonitorReload = true; // for monitor keywords
|
||||||
|
|
||||||
|
g_pInputManager->setKeyboardLayout(); // update kb layout
|
||||||
|
g_pInputManager->setPointerConfigs(); // update mouse cfgs
|
||||||
|
g_pInputManager->setTouchDeviceConfigs(); // update touch device cfgs
|
||||||
|
g_pInputManager->setTabletConfigs(); // update tablets
|
||||||
|
|
||||||
|
static auto* const PLAYOUT = (Hyprlang::STRING const*)g_pConfigManager->getConfigValuePtr("general:layout");
|
||||||
|
|
||||||
|
g_pLayoutManager->switchToLayout(*PLAYOUT); // update layout
|
||||||
|
|
||||||
|
g_pHyprOpenGL->m_bReloadScreenShader = true;
|
||||||
|
|
||||||
|
for (auto& [m, rd] : g_pHyprOpenGL->m_mMonitorRenderResources) {
|
||||||
|
rd.blurFBDirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& m : g_pCompositor->m_vMonitors) {
|
||||||
|
g_pHyprRenderer->damageMonitor(m.get());
|
||||||
|
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m->ID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string HyprCtl::makeDynamicCall(const std::string& input) {
|
std::string CHyprCtl::makeDynamicCall(const std::string& input) {
|
||||||
return getReply(input);
|
return getReply(input);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1460,7 +1571,7 @@ int hyprCtlFDTick(int fd, uint32_t mask, void* data) {
|
||||||
sockaddr_in clientAddress;
|
sockaddr_in clientAddress;
|
||||||
socklen_t clientSize = sizeof(clientAddress);
|
socklen_t clientSize = sizeof(clientAddress);
|
||||||
|
|
||||||
const auto ACCEPTEDCONNECTION = accept4(HyprCtl::iSocketFD, (sockaddr*)&clientAddress, &clientSize, SOCK_CLOEXEC);
|
const auto ACCEPTEDCONNECTION = accept4(g_pHyprCtl->m_iSocketFD, (sockaddr*)&clientAddress, &clientSize, SOCK_CLOEXEC);
|
||||||
|
|
||||||
std::array<char, 1024> readBuffer;
|
std::array<char, 1024> readBuffer;
|
||||||
|
|
||||||
|
@ -1490,7 +1601,7 @@ int hyprCtlFDTick(int fd, uint32_t mask, void* data) {
|
||||||
std::string reply = "";
|
std::string reply = "";
|
||||||
|
|
||||||
try {
|
try {
|
||||||
reply = getReply(request);
|
reply = g_pHyprCtl->getReply(request);
|
||||||
} catch (std::exception& e) {
|
} catch (std::exception& e) {
|
||||||
Debug::log(ERR, "Error in request: {}", e.what());
|
Debug::log(ERR, "Error in request: {}", e.what());
|
||||||
reply = "Err: " + std::string(e.what());
|
reply = "Err: " + std::string(e.what());
|
||||||
|
@ -1500,18 +1611,17 @@ int hyprCtlFDTick(int fd, uint32_t mask, void* data) {
|
||||||
|
|
||||||
close(ACCEPTEDCONNECTION);
|
close(ACCEPTEDCONNECTION);
|
||||||
|
|
||||||
if (g_pConfigManager->m_bWantsMonitorReload) {
|
if (g_pConfigManager->m_bWantsMonitorReload)
|
||||||
g_pConfigManager->ensureMonitorStatus();
|
g_pConfigManager->ensureMonitorStatus();
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void HyprCtl::startHyprCtlSocket() {
|
void CHyprCtl::startHyprCtlSocket() {
|
||||||
|
|
||||||
iSocketFD = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
|
m_iSocketFD = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
|
||||||
|
|
||||||
if (iSocketFD < 0) {
|
if (m_iSocketFD < 0) {
|
||||||
Debug::log(ERR, "Couldn't start the Hyprland Socket. (1) IPC will not work.");
|
Debug::log(ERR, "Couldn't start the Hyprland Socket. (1) IPC will not work.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1522,15 +1632,15 @@ void HyprCtl::startHyprCtlSocket() {
|
||||||
|
|
||||||
strcpy(SERVERADDRESS.sun_path, socketPath.c_str());
|
strcpy(SERVERADDRESS.sun_path, socketPath.c_str());
|
||||||
|
|
||||||
if (bind(iSocketFD, (sockaddr*)&SERVERADDRESS, SUN_LEN(&SERVERADDRESS)) < 0) {
|
if (bind(m_iSocketFD, (sockaddr*)&SERVERADDRESS, SUN_LEN(&SERVERADDRESS)) < 0) {
|
||||||
Debug::log(ERR, "Couldn't start the Hyprland Socket. (2) IPC will not work.");
|
Debug::log(ERR, "Couldn't start the Hyprland Socket. (2) IPC will not work.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 10 max queued.
|
// 10 max queued.
|
||||||
listen(iSocketFD, 10);
|
listen(m_iSocketFD, 10);
|
||||||
|
|
||||||
Debug::log(LOG, "Hypr socket started at {}", socketPath);
|
Debug::log(LOG, "Hypr socket started at {}", socketPath);
|
||||||
|
|
||||||
wl_event_loop_add_fd(g_pCompositor->m_sWLEventLoop, iSocketFD, WL_EVENT_READABLE, hyprCtlFDTick, nullptr);
|
wl_event_loop_add_fd(g_pCompositor->m_sWLEventLoop, m_iSocketFD, WL_EVENT_READABLE, hyprCtlFDTick, nullptr);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,24 +3,23 @@
|
||||||
#include "../Compositor.hpp"
|
#include "../Compositor.hpp"
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include "../helpers/MiscFunctions.hpp"
|
#include "../helpers/MiscFunctions.hpp"
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
namespace HyprCtl {
|
class CHyprCtl {
|
||||||
void startHyprCtlSocket();
|
public:
|
||||||
std::string makeDynamicCall(const std::string& input);
|
CHyprCtl();
|
||||||
|
|
||||||
// very simple thread-safe request method
|
std::string makeDynamicCall(const std::string& input);
|
||||||
inline bool requestMade = false;
|
std::shared_ptr<SHyprCtlCommand> registerCommand(SHyprCtlCommand cmd);
|
||||||
inline bool requestReady = false;
|
void unregisterCommand(const std::shared_ptr<SHyprCtlCommand>& cmd);
|
||||||
inline std::string request = "";
|
std::string getReply(std::string);
|
||||||
|
|
||||||
inline std::ifstream requestStream;
|
int m_iSocketFD = -1;
|
||||||
|
|
||||||
inline wl_event_source* hyprCtlTickSource = nullptr;
|
private:
|
||||||
|
void startHyprCtlSocket();
|
||||||
|
|
||||||
inline int iSocketFD = -1;
|
std::vector<std::shared_ptr<SHyprCtlCommand>> m_vCommands;
|
||||||
|
};
|
||||||
|
|
||||||
enum eHyprCtlOutputFormat {
|
inline std::unique_ptr<CHyprCtl> g_pHyprCtl;
|
||||||
FORMAT_NORMAL = 0,
|
|
||||||
FORMAT_JSON
|
|
||||||
};
|
|
||||||
};
|
|
|
@ -226,4 +226,8 @@ void CHyprNotificationOverlay::draw(CMonitor* pMonitor) {
|
||||||
|
|
||||||
CBox pMonBox = {0, 0, pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y};
|
CBox pMonBox = {0, 0, pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y};
|
||||||
g_pHyprOpenGL->renderTexture(m_tTexture, &pMonBox, 1.f);
|
g_pHyprOpenGL->renderTexture(m_tTexture, &pMonBox, 1.f);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CHyprNotificationOverlay::hasAny() {
|
||||||
|
return !m_dNotifications.empty();
|
||||||
}
|
}
|
|
@ -41,6 +41,7 @@ class CHyprNotificationOverlay {
|
||||||
|
|
||||||
void draw(CMonitor* pMonitor);
|
void draw(CMonitor* pMonitor);
|
||||||
void addNotification(const std::string& text, const CColor& color, const float timeMs, const eIcons icon = ICON_NONE);
|
void addNotification(const std::string& text, const CColor& color, const float timeMs, const eIcons icon = ICON_NONE);
|
||||||
|
bool hasAny();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CBox drawNotifications(CMonitor* pMonitor);
|
CBox drawNotifications(CMonitor* pMonitor);
|
||||||
|
|
|
@ -22,7 +22,7 @@ void Debug::wlrLog(wlr_log_importance level, const char* fmt, va_list args) {
|
||||||
|
|
||||||
rollingLog += output + "\n";
|
rollingLog += output + "\n";
|
||||||
|
|
||||||
if (!disableLogs || !*disableLogs) {
|
if (!disableLogs || !**disableLogs) {
|
||||||
std::ofstream ofs;
|
std::ofstream ofs;
|
||||||
ofs.open(logFile, std::ios::out | std::ios::app);
|
ofs.open(logFile, std::ios::out | std::ios::app);
|
||||||
ofs << "[wlr] " << output << "\n";
|
ofs << "[wlr] " << output << "\n";
|
||||||
|
|
|
@ -21,16 +21,16 @@ enum LogLevel {
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace Debug {
|
namespace Debug {
|
||||||
inline std::string logFile;
|
inline std::string logFile;
|
||||||
inline int64_t* disableLogs = nullptr;
|
inline int64_t* const* disableLogs = nullptr;
|
||||||
inline int64_t* disableTime = nullptr;
|
inline int64_t* const* disableTime = nullptr;
|
||||||
inline bool disableStdout = false;
|
inline bool disableStdout = false;
|
||||||
inline bool trace = false;
|
inline bool trace = false;
|
||||||
inline bool shuttingDown = false;
|
inline bool shuttingDown = false;
|
||||||
|
|
||||||
inline std::string rollingLog = ""; // rolling log contains the ROLLING_LOG_SIZE tail of the log
|
inline std::string rollingLog = ""; // rolling log contains the ROLLING_LOG_SIZE tail of the log
|
||||||
|
|
||||||
void init(const std::string& IS);
|
void init(const std::string& IS);
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
void log(LogLevel level, std::format_string<Args...> fmt, Args&&... args) {
|
void log(LogLevel level, std::format_string<Args...> fmt, Args&&... args) {
|
||||||
if (level == TRACE && !trace)
|
if (level == TRACE && !trace)
|
||||||
|
@ -52,7 +52,7 @@ namespace Debug {
|
||||||
}
|
}
|
||||||
|
|
||||||
// print date and time to the ofs
|
// print date and time to the ofs
|
||||||
if (disableTime && !*disableTime) {
|
if (disableTime && !**disableTime) {
|
||||||
#ifndef _LIBCPP_VERSION
|
#ifndef _LIBCPP_VERSION
|
||||||
logMsg += std::format("[{:%T}] ", std::chrono::hh_mm_ss{std::chrono::system_clock::now() - std::chrono::floor<std::chrono::days>(std::chrono::system_clock::now())});
|
logMsg += std::format("[{:%T}] ", std::chrono::hh_mm_ss{std::chrono::system_clock::now() - std::chrono::floor<std::chrono::days>(std::chrono::system_clock::now())});
|
||||||
#else
|
#else
|
||||||
|
@ -73,7 +73,7 @@ namespace Debug {
|
||||||
if (rollingLog.size() > ROLLING_LOG_SIZE)
|
if (rollingLog.size() > ROLLING_LOG_SIZE)
|
||||||
rollingLog = rollingLog.substr(rollingLog.size() - ROLLING_LOG_SIZE);
|
rollingLog = rollingLog.substr(rollingLog.size() - ROLLING_LOG_SIZE);
|
||||||
|
|
||||||
if (!disableLogs || !*disableLogs) {
|
if (!disableLogs || !**disableLogs) {
|
||||||
// log to a file
|
// log to a file
|
||||||
std::ofstream ofs;
|
std::ofstream ofs;
|
||||||
ofs.open(logFile, std::ios::out | std::ios::app);
|
ofs.open(logFile, std::ios::out | std::ios::app);
|
||||||
|
|
236
src/desktop/Popup.cpp
Normal file
|
@ -0,0 +1,236 @@
|
||||||
|
#include "Popup.hpp"
|
||||||
|
#include "../Compositor.hpp"
|
||||||
|
|
||||||
|
CPopup::CPopup(CWindow* pOwner) : m_pWindowOwner(pOwner) {
|
||||||
|
initAllSignals();
|
||||||
|
}
|
||||||
|
|
||||||
|
CPopup::CPopup(SLayerSurface* pOwner) : m_pLayerOwner(pOwner) {
|
||||||
|
initAllSignals();
|
||||||
|
}
|
||||||
|
|
||||||
|
CPopup::CPopup(wlr_xdg_popup* popup, CPopup* pOwner) : m_pParent(pOwner), m_pWLR(popup) {
|
||||||
|
m_pWLR->base->data = this;
|
||||||
|
m_sWLSurface.assign(popup->base->surface, this);
|
||||||
|
|
||||||
|
m_pLayerOwner = pOwner->m_pLayerOwner;
|
||||||
|
m_pWindowOwner = pOwner->m_pWindowOwner;
|
||||||
|
|
||||||
|
m_vLastSize = {m_pWLR->current.geometry.width, m_pWLR->current.geometry.height};
|
||||||
|
unconstrain();
|
||||||
|
|
||||||
|
initAllSignals();
|
||||||
|
}
|
||||||
|
|
||||||
|
CPopup::~CPopup() {
|
||||||
|
m_sWLSurface.unassign();
|
||||||
|
if (m_pWLR)
|
||||||
|
m_pWLR->base->data = nullptr;
|
||||||
|
|
||||||
|
hyprListener_commitPopup.removeCallback();
|
||||||
|
hyprListener_repositionPopup.removeCallback();
|
||||||
|
hyprListener_mapPopup.removeCallback();
|
||||||
|
hyprListener_unmapPopup.removeCallback();
|
||||||
|
hyprListener_newPopup.removeCallback();
|
||||||
|
hyprListener_destroyPopup.removeCallback();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void onNewPopup(void* owner, void* data) {
|
||||||
|
const auto POPUP = (CPopup*)owner;
|
||||||
|
POPUP->onNewPopup((wlr_xdg_popup*)data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void onMapPopup(void* owner, void* data) {
|
||||||
|
const auto POPUP = (CPopup*)owner;
|
||||||
|
POPUP->onMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void onDestroyPopup(void* owner, void* data) {
|
||||||
|
const auto POPUP = (CPopup*)owner;
|
||||||
|
POPUP->onDestroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void onUnmapPopup(void* owner, void* data) {
|
||||||
|
const auto POPUP = (CPopup*)owner;
|
||||||
|
POPUP->onUnmap();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void onCommitPopup(void* owner, void* data) {
|
||||||
|
const auto POPUP = (CPopup*)owner;
|
||||||
|
POPUP->onCommit();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void onRepositionPopup(void* owner, void* data) {
|
||||||
|
const auto POPUP = (CPopup*)owner;
|
||||||
|
POPUP->onReposition();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPopup::initAllSignals() {
|
||||||
|
|
||||||
|
if (!m_pWLR) {
|
||||||
|
if (m_pWindowOwner)
|
||||||
|
hyprListener_newPopup.initCallback(&m_pWindowOwner->m_uSurface.xdg->events.new_popup, ::onNewPopup, this, "CPopup Head");
|
||||||
|
else if (m_pLayerOwner)
|
||||||
|
hyprListener_newPopup.initCallback(&m_pLayerOwner->layerSurface->events.new_popup, ::onNewPopup, this, "CPopup Head");
|
||||||
|
else
|
||||||
|
ASSERT(false);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
hyprListener_repositionPopup.initCallback(&m_pWLR->events.reposition, ::onRepositionPopup, this, "CPopup");
|
||||||
|
hyprListener_destroyPopup.initCallback(&m_pWLR->events.destroy, ::onDestroyPopup, this, "CPopup");
|
||||||
|
hyprListener_mapPopup.initCallback(&m_sWLSurface.wlr()->events.map, ::onMapPopup, this, "CPopup");
|
||||||
|
hyprListener_unmapPopup.initCallback(&m_sWLSurface.wlr()->events.unmap, ::onUnmapPopup, this, "CPopup");
|
||||||
|
hyprListener_commitPopup.initCallback(&m_sWLSurface.wlr()->events.commit, ::onCommitPopup, this, "CPopup");
|
||||||
|
hyprListener_newPopup.initCallback(&m_pWLR->base->events.new_popup, ::onNewPopup, this, "CPopup");
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPopup::onNewPopup(wlr_xdg_popup* popup) {
|
||||||
|
const auto POPUP = m_vChildren.emplace_back(std::make_unique<CPopup>(popup, this)).get();
|
||||||
|
Debug::log(LOG, "New popup at wlr {:x} and hl {:x}", (uintptr_t)popup, (uintptr_t)POPUP);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPopup::onDestroy() {
|
||||||
|
m_bInert = true;
|
||||||
|
|
||||||
|
if (!m_pParent)
|
||||||
|
return; // head node
|
||||||
|
|
||||||
|
std::erase_if(m_pParent->m_vChildren, [this](const auto& other) { return other.get() == this; });
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPopup::onMap() {
|
||||||
|
m_vLastSize = {m_pWLR->base->current.geometry.width, m_pWLR->base->current.geometry.height};
|
||||||
|
const auto COORDS = coordsGlobal();
|
||||||
|
|
||||||
|
CBox box;
|
||||||
|
wlr_surface_get_extends(m_sWLSurface.wlr(), box.pWlr());
|
||||||
|
box.applyFromWlr().translate(COORDS);
|
||||||
|
g_pHyprRenderer->damageBox(&box);
|
||||||
|
|
||||||
|
m_vLastPos = coordsRelativeToParent();
|
||||||
|
|
||||||
|
g_pInputManager->simulateMouseMovement();
|
||||||
|
|
||||||
|
m_pSubsurfaceHead = std::make_unique<CSubsurface>(this);
|
||||||
|
|
||||||
|
unconstrain();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPopup::onUnmap() {
|
||||||
|
m_vLastSize = {m_pWLR->base->current.geometry.width, m_pWLR->base->current.geometry.height};
|
||||||
|
const auto COORDS = coordsGlobal();
|
||||||
|
|
||||||
|
CBox box;
|
||||||
|
wlr_surface_get_extends(m_sWLSurface.wlr(), box.pWlr());
|
||||||
|
box.applyFromWlr().translate(COORDS);
|
||||||
|
g_pHyprRenderer->damageBox(&box);
|
||||||
|
|
||||||
|
m_pSubsurfaceHead.reset();
|
||||||
|
|
||||||
|
g_pInputManager->simulateMouseMovement();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPopup::onCommit() {
|
||||||
|
if (m_pWLR->base->initial_commit) {
|
||||||
|
wlr_xdg_surface_schedule_configure(m_pWLR->base);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto COORDS = coordsGlobal();
|
||||||
|
const auto COORDSLOCAL = coordsRelativeToParent();
|
||||||
|
|
||||||
|
if (m_vLastSize != Vector2D{m_pWLR->base->current.geometry.width, m_pWLR->base->current.geometry.height} || m_bRequestedReposition || m_vLastPos != COORDSLOCAL) {
|
||||||
|
CBox box = {localToGlobal(m_vLastPos), m_vLastSize};
|
||||||
|
g_pHyprRenderer->damageBox(&box);
|
||||||
|
m_vLastSize = {m_pWLR->base->current.geometry.width, m_pWLR->base->current.geometry.height};
|
||||||
|
box = {COORDS, m_vLastSize};
|
||||||
|
g_pHyprRenderer->damageBox(&box);
|
||||||
|
|
||||||
|
m_vLastPos = COORDSLOCAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_pSubsurfaceHead->recheckDamageForSubsurfaces();
|
||||||
|
|
||||||
|
g_pHyprRenderer->damageSurface(m_sWLSurface.wlr(), COORDS.x, COORDS.y);
|
||||||
|
|
||||||
|
m_bRequestedReposition = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPopup::onReposition() {
|
||||||
|
Debug::log(LOG, "Popup {:x} requests reposition", (uintptr_t)this);
|
||||||
|
|
||||||
|
m_bRequestedReposition = true;
|
||||||
|
|
||||||
|
m_vLastPos = coordsRelativeToParent();
|
||||||
|
|
||||||
|
unconstrain();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPopup::unconstrain() {
|
||||||
|
const auto COORDS = t1ParentCoords();
|
||||||
|
const auto PMONITOR = g_pCompositor->getMonitorFromVector(COORDS);
|
||||||
|
|
||||||
|
if (!PMONITOR)
|
||||||
|
return;
|
||||||
|
|
||||||
|
CBox box = {PMONITOR->vecPosition.x - COORDS.x, PMONITOR->vecPosition.y - COORDS.y, PMONITOR->vecSize.x, PMONITOR->vecSize.y};
|
||||||
|
wlr_xdg_popup_unconstrain_from_box(m_pWLR, box.pWlr());
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector2D CPopup::coordsRelativeToParent() {
|
||||||
|
Vector2D offset;
|
||||||
|
|
||||||
|
CPopup* current = this;
|
||||||
|
|
||||||
|
offset -= {m_pWLR->base->current.geometry.x, m_pWLR->base->current.geometry.y};
|
||||||
|
|
||||||
|
while (current->m_pParent) {
|
||||||
|
|
||||||
|
offset += {current->m_sWLSurface.wlr()->current.dx, current->m_sWLSurface.wlr()->current.dy};
|
||||||
|
offset += {current->m_pWLR->current.geometry.x, current->m_pWLR->current.geometry.y};
|
||||||
|
|
||||||
|
current = current->m_pParent;
|
||||||
|
}
|
||||||
|
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector2D CPopup::coordsGlobal() {
|
||||||
|
return localToGlobal(coordsRelativeToParent());
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector2D CPopup::localToGlobal(const Vector2D& rel) {
|
||||||
|
return t1ParentCoords() + rel;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector2D CPopup::t1ParentCoords() {
|
||||||
|
if (m_pWindowOwner)
|
||||||
|
return m_pWindowOwner->m_vRealPosition.value();
|
||||||
|
if (m_pLayerOwner)
|
||||||
|
return m_pLayerOwner->realPosition.value();
|
||||||
|
|
||||||
|
ASSERT(false);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPopup::recheckTree() {
|
||||||
|
CPopup* curr = this;
|
||||||
|
while (curr->m_pParent) {
|
||||||
|
curr = curr->m_pParent;
|
||||||
|
}
|
||||||
|
|
||||||
|
curr->recheckChildrenRecursive();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPopup::recheckChildrenRecursive() {
|
||||||
|
for (auto& c : m_vChildren) {
|
||||||
|
c->onCommit();
|
||||||
|
c->recheckChildrenRecursive();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector2D CPopup::size() {
|
||||||
|
return m_vLastSize;
|
||||||
|
}
|
71
src/desktop/Popup.hpp
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <memory>
|
||||||
|
#include "Subsurface.hpp"
|
||||||
|
|
||||||
|
struct SLayerSurface;
|
||||||
|
|
||||||
|
class CPopup {
|
||||||
|
public:
|
||||||
|
// dummy head nodes
|
||||||
|
CPopup(CWindow* pOwner);
|
||||||
|
CPopup(SLayerSurface* pOwner);
|
||||||
|
|
||||||
|
// real nodes
|
||||||
|
CPopup(wlr_xdg_popup* popup, CPopup* pOwner);
|
||||||
|
|
||||||
|
~CPopup();
|
||||||
|
|
||||||
|
Vector2D coordsRelativeToParent();
|
||||||
|
Vector2D coordsGlobal();
|
||||||
|
|
||||||
|
Vector2D size();
|
||||||
|
|
||||||
|
void onNewPopup(wlr_xdg_popup* popup);
|
||||||
|
void onDestroy();
|
||||||
|
void onMap();
|
||||||
|
void onUnmap();
|
||||||
|
void onCommit();
|
||||||
|
void onReposition();
|
||||||
|
|
||||||
|
void recheckTree();
|
||||||
|
|
||||||
|
CWLSurface m_sWLSurface;
|
||||||
|
|
||||||
|
private:
|
||||||
|
// T1 owners, each popup has to have one of these
|
||||||
|
CWindow* m_pWindowOwner = nullptr;
|
||||||
|
SLayerSurface* m_pLayerOwner = nullptr;
|
||||||
|
|
||||||
|
// T2 owners
|
||||||
|
CPopup* m_pParent = nullptr;
|
||||||
|
|
||||||
|
wlr_xdg_popup* m_pWLR = nullptr;
|
||||||
|
|
||||||
|
Vector2D m_vLastSize = {};
|
||||||
|
Vector2D m_vLastPos = {};
|
||||||
|
|
||||||
|
bool m_bRequestedReposition = false;
|
||||||
|
|
||||||
|
bool m_bInert = false;
|
||||||
|
|
||||||
|
//
|
||||||
|
std::vector<std::unique_ptr<CPopup>> m_vChildren;
|
||||||
|
std::unique_ptr<CSubsurface> m_pSubsurfaceHead;
|
||||||
|
|
||||||
|
// signals
|
||||||
|
DYNLISTENER(newPopup);
|
||||||
|
DYNLISTENER(destroyPopup);
|
||||||
|
DYNLISTENER(mapPopup);
|
||||||
|
DYNLISTENER(unmapPopup);
|
||||||
|
DYNLISTENER(commitPopup);
|
||||||
|
DYNLISTENER(repositionPopup);
|
||||||
|
|
||||||
|
void initAllSignals();
|
||||||
|
void unconstrain();
|
||||||
|
void recheckChildrenRecursive();
|
||||||
|
|
||||||
|
Vector2D localToGlobal(const Vector2D& rel);
|
||||||
|
Vector2D t1ParentCoords();
|
||||||
|
};
|
261
src/desktop/Subsurface.cpp
Normal file
|
@ -0,0 +1,261 @@
|
||||||
|
#include "Subsurface.hpp"
|
||||||
|
#include "../events/Events.hpp"
|
||||||
|
#include "../Compositor.hpp"
|
||||||
|
|
||||||
|
static void onNewSubsurface(void* owner, void* data);
|
||||||
|
|
||||||
|
CSubsurface::CSubsurface(CWindow* pOwner) : m_pWindowParent(pOwner) {
|
||||||
|
initSignals();
|
||||||
|
|
||||||
|
wlr_subsurface* wlrSubsurface;
|
||||||
|
wl_list_for_each(wlrSubsurface, &pOwner->m_pWLSurface.wlr()->current.subsurfaces_below, current.link) {
|
||||||
|
::onNewSubsurface(this, wlrSubsurface);
|
||||||
|
}
|
||||||
|
wl_list_for_each(wlrSubsurface, &pOwner->m_pWLSurface.wlr()->current.subsurfaces_above, current.link) {
|
||||||
|
::onNewSubsurface(this, wlrSubsurface);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CSubsurface::CSubsurface(CPopup* pOwner) : m_pPopupParent(pOwner) {
|
||||||
|
initSignals();
|
||||||
|
|
||||||
|
wlr_subsurface* wlrSubsurface;
|
||||||
|
wl_list_for_each(wlrSubsurface, &pOwner->m_sWLSurface.wlr()->current.subsurfaces_below, current.link) {
|
||||||
|
::onNewSubsurface(this, wlrSubsurface);
|
||||||
|
}
|
||||||
|
wl_list_for_each(wlrSubsurface, &pOwner->m_sWLSurface.wlr()->current.subsurfaces_above, current.link) {
|
||||||
|
::onNewSubsurface(this, wlrSubsurface);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CSubsurface::CSubsurface(wlr_subsurface* pSubsurface, CWindow* pOwner) : m_pSubsurface(pSubsurface), m_pWindowParent(pOwner) {
|
||||||
|
m_sWLSurface.assign(pSubsurface->surface, this);
|
||||||
|
initSignals();
|
||||||
|
initExistingSubsurfaces();
|
||||||
|
}
|
||||||
|
|
||||||
|
CSubsurface::CSubsurface(wlr_subsurface* pSubsurface, CPopup* pOwner) : m_pSubsurface(pSubsurface), m_pPopupParent(pOwner) {
|
||||||
|
m_sWLSurface.assign(pSubsurface->surface, this);
|
||||||
|
initSignals();
|
||||||
|
initExistingSubsurfaces();
|
||||||
|
}
|
||||||
|
|
||||||
|
CSubsurface::~CSubsurface() {
|
||||||
|
hyprListener_newSubsurface.removeCallback();
|
||||||
|
|
||||||
|
if (!m_pSubsurface)
|
||||||
|
return;
|
||||||
|
|
||||||
|
hyprListener_commitSubsurface.removeCallback();
|
||||||
|
hyprListener_destroySubsurface.removeCallback();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void onNewSubsurface(void* owner, void* data) {
|
||||||
|
const auto PSUBSURFACE = (CSubsurface*)owner;
|
||||||
|
PSUBSURFACE->onNewSubsurface((wlr_subsurface*)data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void onDestroySubsurface(void* owner, void* data) {
|
||||||
|
const auto PSUBSURFACE = (CSubsurface*)owner;
|
||||||
|
PSUBSURFACE->onDestroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void onCommitSubsurface(void* owner, void* data) {
|
||||||
|
const auto PSUBSURFACE = (CSubsurface*)owner;
|
||||||
|
PSUBSURFACE->onCommit();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void onMapSubsurface(void* owner, void* data) {
|
||||||
|
const auto PSUBSURFACE = (CSubsurface*)owner;
|
||||||
|
PSUBSURFACE->onMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void onUnmapSubsurface(void* owner, void* data) {
|
||||||
|
const auto PSUBSURFACE = (CSubsurface*)owner;
|
||||||
|
PSUBSURFACE->onUnmap();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSubsurface::initSignals() {
|
||||||
|
if (m_pSubsurface) {
|
||||||
|
hyprListener_commitSubsurface.initCallback(&m_pSubsurface->surface->events.commit, &onCommitSubsurface, this, "CSubsurface");
|
||||||
|
hyprListener_destroySubsurface.initCallback(&m_pSubsurface->events.destroy, &onDestroySubsurface, this, "CSubsurface");
|
||||||
|
hyprListener_newSubsurface.initCallback(&m_pSubsurface->surface->events.new_subsurface, &::onNewSubsurface, this, "CSubsurface");
|
||||||
|
hyprListener_mapSubsurface.initCallback(&m_pSubsurface->surface->events.map, &onMapSubsurface, this, "CSubsurface");
|
||||||
|
hyprListener_unmapSubsurface.initCallback(&m_pSubsurface->surface->events.unmap, &onUnmapSubsurface, this, "CSubsurface");
|
||||||
|
} else {
|
||||||
|
if (m_pWindowParent)
|
||||||
|
hyprListener_newSubsurface.initCallback(&m_pWindowParent->m_pWLSurface.wlr()->events.new_subsurface, &::onNewSubsurface, this, "CSubsurface Head");
|
||||||
|
else if (m_pPopupParent)
|
||||||
|
hyprListener_newSubsurface.initCallback(&m_pPopupParent->m_sWLSurface.wlr()->events.new_subsurface, &::onNewSubsurface, this, "CSubsurface Head");
|
||||||
|
else
|
||||||
|
RASSERT(false, "CSubsurface::initSignals empty subsurface");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSubsurface::checkSiblingDamage() {
|
||||||
|
if (!m_pParent)
|
||||||
|
return; // ??????????
|
||||||
|
|
||||||
|
const double SCALE = m_pWindowParent && m_pWindowParent->m_bIsX11 ? 1.0 / m_pWindowParent->m_fX11SurfaceScaledBy : 1.0;
|
||||||
|
|
||||||
|
for (auto& n : m_pParent->m_vChildren) {
|
||||||
|
if (n.get() == this)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const auto COORDS = n->coordsGlobal();
|
||||||
|
g_pHyprRenderer->damageSurface(n->m_sWLSurface.wlr(), COORDS.x, COORDS.y, SCALE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSubsurface::recheckDamageForSubsurfaces() {
|
||||||
|
for (auto& n : m_vChildren) {
|
||||||
|
const auto COORDS = n->coordsGlobal();
|
||||||
|
g_pHyprRenderer->damageSurface(n->m_sWLSurface.wlr(), COORDS.x, COORDS.y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSubsurface::onCommit() {
|
||||||
|
// no damaging if it's not visible
|
||||||
|
if (!g_pHyprRenderer->shouldRenderWindow(m_pWindowParent)) {
|
||||||
|
m_vLastSize = Vector2D{m_sWLSurface.wlr()->current.width, m_sWLSurface.wlr()->current.height};
|
||||||
|
|
||||||
|
static auto* const PLOGDAMAGE = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("debug:log_damage");
|
||||||
|
if (**PLOGDAMAGE)
|
||||||
|
Debug::log(LOG, "Refusing to commit damage from a subsurface of {} because it's invisible.", m_pWindowParent);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto COORDS = coordsGlobal();
|
||||||
|
|
||||||
|
g_pHyprRenderer->damageSurface(m_sWLSurface.wlr(), COORDS.x, COORDS.y);
|
||||||
|
|
||||||
|
if (m_pPopupParent)
|
||||||
|
m_pPopupParent->recheckTree();
|
||||||
|
if (m_pWindowParent) // I hate you firefox why are you doing this
|
||||||
|
m_pWindowParent->m_pPopupHead->recheckTree();
|
||||||
|
|
||||||
|
// I do not think this is correct, but it solves a lot of issues with some apps (e.g. firefox)
|
||||||
|
checkSiblingDamage();
|
||||||
|
|
||||||
|
if (m_vLastSize != Vector2D{m_sWLSurface.wlr()->current.width, m_sWLSurface.wlr()->current.height}) {
|
||||||
|
CBox box{COORDS, m_vLastSize};
|
||||||
|
g_pHyprRenderer->damageBox(&box);
|
||||||
|
m_vLastSize = Vector2D{m_sWLSurface.wlr()->current.width, m_sWLSurface.wlr()->current.height};
|
||||||
|
box = {COORDS, m_vLastSize};
|
||||||
|
g_pHyprRenderer->damageBox(&box);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_pWindowParent) {
|
||||||
|
// tearing: if solitary, redraw it. This still might be a single surface window
|
||||||
|
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_pWindowParent->m_iMonitorID);
|
||||||
|
if (PMONITOR && PMONITOR->solitaryClient == m_pWindowParent && m_pWindowParent->canBeTorn() && PMONITOR->tearingState.canTear &&
|
||||||
|
m_sWLSurface.wlr()->current.committed & WLR_SURFACE_STATE_BUFFER) {
|
||||||
|
CRegion damageBox{&m_sWLSurface.wlr()->buffer_damage};
|
||||||
|
|
||||||
|
if (!damageBox.empty()) {
|
||||||
|
if (PMONITOR->tearingState.busy) {
|
||||||
|
PMONITOR->tearingState.frameScheduledWhileBusy = true;
|
||||||
|
} else {
|
||||||
|
PMONITOR->tearingState.nextRenderTorn = true;
|
||||||
|
g_pHyprRenderer->renderMonitor(PMONITOR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSubsurface::onDestroy() {
|
||||||
|
// destroy children
|
||||||
|
m_vChildren.clear();
|
||||||
|
|
||||||
|
m_bInert = true;
|
||||||
|
|
||||||
|
if (!m_pSubsurface)
|
||||||
|
return; // dummy node, nothing to do, it's the parent dying
|
||||||
|
|
||||||
|
// kill ourselves
|
||||||
|
std::erase_if(m_pParent->m_vChildren, [this](const auto& other) { return other.get() == this; });
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSubsurface::onNewSubsurface(wlr_subsurface* pSubsurface) {
|
||||||
|
CSubsurface* PSUBSURFACE = nullptr;
|
||||||
|
|
||||||
|
if (m_pWindowParent)
|
||||||
|
PSUBSURFACE = m_vChildren.emplace_back(std::make_unique<CSubsurface>(pSubsurface, m_pWindowParent)).get();
|
||||||
|
else if (m_pPopupParent)
|
||||||
|
PSUBSURFACE = m_vChildren.emplace_back(std::make_unique<CSubsurface>(pSubsurface, m_pPopupParent)).get();
|
||||||
|
PSUBSURFACE->m_pParent = this;
|
||||||
|
|
||||||
|
ASSERT(PSUBSURFACE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSubsurface::onMap() {
|
||||||
|
m_vLastSize = {m_sWLSurface.wlr()->current.width, m_sWLSurface.wlr()->current.height};
|
||||||
|
|
||||||
|
const auto COORDS = coordsGlobal();
|
||||||
|
CBox box{COORDS, m_vLastSize};
|
||||||
|
g_pHyprRenderer->damageBox(&box);
|
||||||
|
|
||||||
|
if (m_pWindowParent)
|
||||||
|
m_pWindowParent->updateSurfaceScaleTransformDetails();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSubsurface::onUnmap() {
|
||||||
|
const auto COORDS = coordsGlobal();
|
||||||
|
CBox box{COORDS, m_vLastSize};
|
||||||
|
g_pHyprRenderer->damageBox(&box);
|
||||||
|
|
||||||
|
if (m_sWLSurface.wlr() == g_pCompositor->m_pLastFocus)
|
||||||
|
g_pInputManager->releaseAllMouseButtons();
|
||||||
|
|
||||||
|
if (m_pWindowParent)
|
||||||
|
m_pWindowParent->updateSurfaceScaleTransformDetails();
|
||||||
|
|
||||||
|
g_pInputManager->simulateMouseMovement();
|
||||||
|
|
||||||
|
// TODO: should this remove children? Currently it won't, only on .destroy
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector2D CSubsurface::coordsRelativeToParent() {
|
||||||
|
Vector2D offset;
|
||||||
|
|
||||||
|
CSubsurface* current = this;
|
||||||
|
|
||||||
|
while (current->m_pParent) {
|
||||||
|
|
||||||
|
offset += {current->m_sWLSurface.wlr()->current.dx, current->m_sWLSurface.wlr()->current.dy};
|
||||||
|
offset += {current->m_pSubsurface->current.x, current->m_pSubsurface->current.y};
|
||||||
|
|
||||||
|
current = current->m_pParent;
|
||||||
|
}
|
||||||
|
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector2D CSubsurface::coordsGlobal() {
|
||||||
|
Vector2D coords = coordsRelativeToParent();
|
||||||
|
|
||||||
|
if (m_pWindowParent)
|
||||||
|
coords += m_pWindowParent->m_vRealPosition.value();
|
||||||
|
else if (m_pPopupParent)
|
||||||
|
coords += m_pPopupParent->coordsGlobal();
|
||||||
|
|
||||||
|
return coords;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSubsurface::initExistingSubsurfaces() {
|
||||||
|
if (m_pWindowParent)
|
||||||
|
return;
|
||||||
|
|
||||||
|
wlr_subsurface* wlrSubsurface;
|
||||||
|
wl_list_for_each(wlrSubsurface, &m_sWLSurface.wlr()->current.subsurfaces_below, current.link) {
|
||||||
|
::onNewSubsurface(this, wlrSubsurface);
|
||||||
|
}
|
||||||
|
wl_list_for_each(wlrSubsurface, &m_sWLSurface.wlr()->current.subsurfaces_above, current.link) {
|
||||||
|
::onNewSubsurface(this, wlrSubsurface);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector2D CSubsurface::size() {
|
||||||
|
return {m_sWLSurface.wlr()->current.width, m_sWLSurface.wlr()->current.height};
|
||||||
|
}
|
59
src/desktop/Subsurface.hpp
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../defines.hpp"
|
||||||
|
#include <vector>
|
||||||
|
#include "WLSurface.hpp"
|
||||||
|
|
||||||
|
class CWindow;
|
||||||
|
class CPopup;
|
||||||
|
|
||||||
|
class CSubsurface {
|
||||||
|
public:
|
||||||
|
// root dummy nodes
|
||||||
|
CSubsurface(CWindow* pOwner);
|
||||||
|
CSubsurface(CPopup* pOwner);
|
||||||
|
|
||||||
|
// real nodes
|
||||||
|
CSubsurface(wlr_subsurface* pSubsurface, CWindow* pOwner);
|
||||||
|
CSubsurface(wlr_subsurface* pSubsurface, CPopup* pOwner);
|
||||||
|
|
||||||
|
~CSubsurface();
|
||||||
|
|
||||||
|
Vector2D coordsRelativeToParent();
|
||||||
|
Vector2D coordsGlobal();
|
||||||
|
|
||||||
|
Vector2D size();
|
||||||
|
|
||||||
|
void onCommit();
|
||||||
|
void onDestroy();
|
||||||
|
void onNewSubsurface(wlr_subsurface* pSubsurface);
|
||||||
|
void onMap();
|
||||||
|
void onUnmap();
|
||||||
|
|
||||||
|
void recheckDamageForSubsurfaces();
|
||||||
|
|
||||||
|
private:
|
||||||
|
DYNLISTENER(destroySubsurface);
|
||||||
|
DYNLISTENER(commitSubsurface);
|
||||||
|
DYNLISTENER(newSubsurface);
|
||||||
|
DYNLISTENER(mapSubsurface);
|
||||||
|
DYNLISTENER(unmapSubsurface);
|
||||||
|
|
||||||
|
wlr_subsurface* m_pSubsurface = nullptr;
|
||||||
|
CWLSurface m_sWLSurface;
|
||||||
|
Vector2D m_vLastSize = {};
|
||||||
|
|
||||||
|
// if nullptr, means it's a dummy node
|
||||||
|
CSubsurface* m_pParent = nullptr;
|
||||||
|
|
||||||
|
CWindow* m_pWindowParent = nullptr;
|
||||||
|
CPopup* m_pPopupParent = nullptr;
|
||||||
|
|
||||||
|
std::vector<std::unique_ptr<CSubsurface>> m_vChildren;
|
||||||
|
|
||||||
|
bool m_bInert = false;
|
||||||
|
|
||||||
|
void initSignals();
|
||||||
|
void initExistingSubsurfaces();
|
||||||
|
void checkSiblingDamage();
|
||||||
|
};
|
174
src/desktop/WLSurface.cpp
Normal file
|
@ -0,0 +1,174 @@
|
||||||
|
#include "WLSurface.hpp"
|
||||||
|
#include "../Compositor.hpp"
|
||||||
|
|
||||||
|
void CWLSurface::assign(wlr_surface* pSurface) {
|
||||||
|
m_pWLRSurface = pSurface;
|
||||||
|
init();
|
||||||
|
m_bInert = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CWLSurface::assign(wlr_surface* pSurface, CWindow* pOwner) {
|
||||||
|
m_pWindowOwner = pOwner;
|
||||||
|
m_pWLRSurface = pSurface;
|
||||||
|
init();
|
||||||
|
m_bInert = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CWLSurface::assign(wlr_surface* pSurface, SLayerSurface* pOwner) {
|
||||||
|
m_pLayerOwner = pOwner;
|
||||||
|
m_pWLRSurface = pSurface;
|
||||||
|
init();
|
||||||
|
m_bInert = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CWLSurface::assign(wlr_surface* pSurface, CSubsurface* pOwner) {
|
||||||
|
m_pSubsurfaceOwner = pOwner;
|
||||||
|
m_pWLRSurface = pSurface;
|
||||||
|
init();
|
||||||
|
m_bInert = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CWLSurface::assign(wlr_surface* pSurface, CPopup* pOwner) {
|
||||||
|
m_pPopupOwner = pOwner;
|
||||||
|
m_pWLRSurface = pSurface;
|
||||||
|
init();
|
||||||
|
m_bInert = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CWLSurface::unassign() {
|
||||||
|
destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
CWLSurface::~CWLSurface() {
|
||||||
|
destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CWLSurface::exists() const {
|
||||||
|
return m_pWLRSurface;
|
||||||
|
}
|
||||||
|
|
||||||
|
wlr_surface* CWLSurface::wlr() const {
|
||||||
|
return m_pWLRSurface;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CWLSurface::small() const {
|
||||||
|
if (!m_pWindowOwner || !exists())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return m_pWindowOwner->m_vReportedSize.x > m_pWLRSurface->current.buffer_width + 1 || m_pWindowOwner->m_vReportedSize.y > m_pWLRSurface->current.buffer_height + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector2D CWLSurface::correctSmallVec() const {
|
||||||
|
if (!m_pWindowOwner || !exists() || !small() || m_bFillIgnoreSmall)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
const auto SIZE = getViewporterCorrectedSize();
|
||||||
|
|
||||||
|
return Vector2D{(m_pWindowOwner->m_vReportedSize.x - SIZE.x) / 2, (m_pWindowOwner->m_vReportedSize.y - SIZE.y) / 2}.clamp({}, {INFINITY, INFINITY}) *
|
||||||
|
(m_pWindowOwner->m_vRealSize.value() / m_pWindowOwner->m_vReportedSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector2D CWLSurface::getViewporterCorrectedSize() const {
|
||||||
|
if (!exists())
|
||||||
|
return {};
|
||||||
|
|
||||||
|
return m_pWLRSurface->current.viewport.has_dst ? Vector2D{m_pWLRSurface->current.viewport.dst_width, m_pWLRSurface->current.viewport.dst_height} :
|
||||||
|
Vector2D{m_pWLRSurface->current.buffer_width, m_pWLRSurface->current.buffer_height};
|
||||||
|
}
|
||||||
|
|
||||||
|
CRegion CWLSurface::logicalDamage() const {
|
||||||
|
CRegion damage{&m_pWLRSurface->buffer_damage};
|
||||||
|
damage.transform(m_pWLRSurface->current.transform, m_pWLRSurface->current.buffer_width, m_pWLRSurface->current.buffer_height);
|
||||||
|
damage.scale(1.0 / m_pWLRSurface->current.scale);
|
||||||
|
|
||||||
|
const auto VPSIZE = getViewporterCorrectedSize();
|
||||||
|
const auto CORRECTVEC = correctSmallVec();
|
||||||
|
|
||||||
|
if (m_pWLRSurface->current.viewport.has_src) {
|
||||||
|
damage.intersect(CBox{std::floor(m_pWLRSurface->current.viewport.src.x), std::floor(m_pWLRSurface->current.viewport.src.y),
|
||||||
|
std::ceil(m_pWLRSurface->current.viewport.src.width), std::ceil(m_pWLRSurface->current.viewport.src.height)});
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto SCALEDSRCSIZE = m_pWLRSurface->current.viewport.has_src ?
|
||||||
|
Vector2D{m_pWLRSurface->current.viewport.src.width, m_pWLRSurface->current.viewport.src.height} * m_pWLRSurface->current.scale :
|
||||||
|
Vector2D{m_pWLRSurface->current.buffer_width, m_pWLRSurface->current.buffer_height};
|
||||||
|
|
||||||
|
damage.scale({VPSIZE.x / SCALEDSRCSIZE.x, VPSIZE.y / SCALEDSRCSIZE.y});
|
||||||
|
damage.translate(CORRECTVEC);
|
||||||
|
|
||||||
|
return damage;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CWLSurface::destroy() {
|
||||||
|
if (!m_pWLRSurface)
|
||||||
|
return;
|
||||||
|
|
||||||
|
hyprListener_destroy.removeCallback();
|
||||||
|
m_pWLRSurface->data = nullptr;
|
||||||
|
m_pWindowOwner = nullptr;
|
||||||
|
m_pLayerOwner = nullptr;
|
||||||
|
m_pPopupOwner = nullptr;
|
||||||
|
m_pSubsurfaceOwner = nullptr;
|
||||||
|
m_bInert = true;
|
||||||
|
|
||||||
|
if (g_pCompositor && g_pCompositor->m_pLastFocus == m_pWLRSurface)
|
||||||
|
g_pCompositor->m_pLastFocus = nullptr;
|
||||||
|
if (g_pInputManager && g_pInputManager->m_pLastMouseSurface == m_pWLRSurface)
|
||||||
|
g_pInputManager->m_pLastMouseSurface = nullptr;
|
||||||
|
if (g_pHyprRenderer && g_pHyprRenderer->m_sLastCursorData.surf == m_pWLRSurface)
|
||||||
|
g_pHyprRenderer->m_sLastCursorData.surf.reset();
|
||||||
|
|
||||||
|
m_pWLRSurface = nullptr;
|
||||||
|
|
||||||
|
Debug::log(LOG, "CWLSurface {:x} called destroy()", (uintptr_t)this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CWLSurface::init() {
|
||||||
|
if (!m_pWLRSurface)
|
||||||
|
return;
|
||||||
|
|
||||||
|
RASSERT(!m_pWLRSurface->data, "Attempted to duplicate CWLSurface ownership!");
|
||||||
|
|
||||||
|
m_pWLRSurface->data = this;
|
||||||
|
|
||||||
|
hyprListener_destroy.initCallback(
|
||||||
|
&m_pWLRSurface->events.destroy, [&](void* owner, void* data) { destroy(); }, this, "CWLSurface");
|
||||||
|
|
||||||
|
Debug::log(LOG, "CWLSurface {:x} called init()", (uintptr_t)this);
|
||||||
|
}
|
||||||
|
|
||||||
|
CWindow* CWLSurface::getWindow() {
|
||||||
|
return m_pWindowOwner;
|
||||||
|
}
|
||||||
|
|
||||||
|
SLayerSurface* CWLSurface::getLayer() {
|
||||||
|
return m_pLayerOwner;
|
||||||
|
}
|
||||||
|
|
||||||
|
CPopup* CWLSurface::getPopup() {
|
||||||
|
return m_pPopupOwner;
|
||||||
|
}
|
||||||
|
|
||||||
|
CSubsurface* CWLSurface::getSubsurface() {
|
||||||
|
return m_pSubsurfaceOwner;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CWLSurface::desktopComponent() {
|
||||||
|
return m_pLayerOwner || m_pWindowOwner || m_pSubsurfaceOwner || m_pPopupOwner;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<CBox> CWLSurface::getSurfaceBoxGlobal() {
|
||||||
|
if (!desktopComponent())
|
||||||
|
return {};
|
||||||
|
|
||||||
|
if (m_pWindowOwner)
|
||||||
|
return m_pWindowOwner->getWindowMainSurfaceBox();
|
||||||
|
if (m_pLayerOwner)
|
||||||
|
return m_pLayerOwner->geometry;
|
||||||
|
if (m_pPopupOwner)
|
||||||
|
return CBox{m_pPopupOwner->coordsGlobal(), m_pPopupOwner->size()};
|
||||||
|
if (m_pSubsurfaceOwner)
|
||||||
|
return CBox{m_pSubsurfaceOwner->coordsGlobal(), m_pSubsurfaceOwner->size()};
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
|
@ -1,16 +1,24 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "../defines.hpp"
|
#include "../defines.hpp"
|
||||||
|
#include "../helpers/Region.hpp"
|
||||||
|
|
||||||
class CWindow;
|
class CWindow;
|
||||||
|
struct SLayerSurface;
|
||||||
|
class CSubsurface;
|
||||||
|
class CPopup;
|
||||||
|
|
||||||
class CWLSurface {
|
class CWLSurface {
|
||||||
public:
|
public:
|
||||||
CWLSurface() = default;
|
CWLSurface() = default;
|
||||||
CWLSurface(wlr_surface* pSurface);
|
|
||||||
~CWLSurface();
|
~CWLSurface();
|
||||||
|
|
||||||
|
// anonymous surfaces are non-desktop components, e.g. a cursor surface or a DnD
|
||||||
void assign(wlr_surface* pSurface);
|
void assign(wlr_surface* pSurface);
|
||||||
|
void assign(wlr_surface* pSurface, CWindow* pOwner);
|
||||||
|
void assign(wlr_surface* pSurface, SLayerSurface* pOwner);
|
||||||
|
void assign(wlr_surface* pSurface, CSubsurface* pOwner);
|
||||||
|
void assign(wlr_surface* pSurface, CPopup* pOwner);
|
||||||
void unassign();
|
void unassign();
|
||||||
|
|
||||||
CWLSurface(const CWLSurface&) = delete;
|
CWLSurface(const CWLSurface&) = delete;
|
||||||
|
@ -23,13 +31,26 @@ class CWLSurface {
|
||||||
bool small() const; // means surface is smaller than the requested size
|
bool small() const; // means surface is smaller than the requested size
|
||||||
Vector2D correctSmallVec() const; // returns a corrective vector for small() surfaces
|
Vector2D correctSmallVec() const; // returns a corrective vector for small() surfaces
|
||||||
Vector2D getViewporterCorrectedSize() const;
|
Vector2D getViewporterCorrectedSize() const;
|
||||||
|
CRegion logicalDamage() const;
|
||||||
|
|
||||||
|
// getters for owners.
|
||||||
|
CWindow* getWindow();
|
||||||
|
SLayerSurface* getLayer();
|
||||||
|
CPopup* getPopup();
|
||||||
|
CSubsurface* getSubsurface();
|
||||||
|
|
||||||
|
// desktop components misc utils
|
||||||
|
std::optional<CBox> getSurfaceBoxGlobal();
|
||||||
|
|
||||||
// allow stretching. Useful for plugins.
|
// allow stretching. Useful for plugins.
|
||||||
bool m_bFillIgnoreSmall = false;
|
bool m_bFillIgnoreSmall = false;
|
||||||
|
|
||||||
// if present, means this is a base surface of a window. Cleaned on unassign()
|
// track surface data and avoid dupes
|
||||||
CWindow* m_pOwner = nullptr;
|
float m_fLastScale = 0;
|
||||||
|
int m_iLastScale = 0;
|
||||||
|
wl_output_transform m_eLastTransform = (wl_output_transform)-1;
|
||||||
|
|
||||||
|
//
|
||||||
CWLSurface& operator=(wlr_surface* pSurface) {
|
CWLSurface& operator=(wlr_surface* pSurface) {
|
||||||
destroy();
|
destroy();
|
||||||
m_pWLRSurface = pSurface;
|
m_pWLRSurface = pSurface;
|
||||||
|
@ -55,10 +76,18 @@ class CWLSurface {
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
wlr_surface* m_pWLRSurface = nullptr;
|
bool m_bInert = true;
|
||||||
|
|
||||||
void destroy();
|
wlr_surface* m_pWLRSurface = nullptr;
|
||||||
void init();
|
|
||||||
|
CWindow* m_pWindowOwner = nullptr;
|
||||||
|
SLayerSurface* m_pLayerOwner = nullptr;
|
||||||
|
CPopup* m_pPopupOwner = nullptr;
|
||||||
|
CSubsurface* m_pSubsurfaceOwner = nullptr;
|
||||||
|
|
||||||
|
void destroy();
|
||||||
|
void init();
|
||||||
|
bool desktopComponent();
|
||||||
|
|
||||||
DYNLISTENER(destroy);
|
DYNLISTENER(destroy);
|
||||||
};
|
};
|
|
@ -14,8 +14,8 @@ CWorkspace::CWorkspace(int monitorID, std::string name, bool special) {
|
||||||
m_bIsSpecialWorkspace = special;
|
m_bIsSpecialWorkspace = special;
|
||||||
|
|
||||||
m_vRenderOffset.m_pWorkspace = this;
|
m_vRenderOffset.m_pWorkspace = this;
|
||||||
m_vRenderOffset.create(AVARTYPE_VECTOR, special ? g_pConfigManager->getAnimationPropertyConfig("specialWorkspace") : g_pConfigManager->getAnimationPropertyConfig("workspaces"),
|
m_vRenderOffset.create(special ? g_pConfigManager->getAnimationPropertyConfig("specialWorkspace") : g_pConfigManager->getAnimationPropertyConfig("workspaces"), nullptr,
|
||||||
nullptr, AVARDAMAGE_ENTIRE);
|
AVARDAMAGE_ENTIRE);
|
||||||
m_fAlpha.m_pWorkspace = this;
|
m_fAlpha.m_pWorkspace = this;
|
||||||
m_fAlpha.create(AVARTYPE_FLOAT, special ? g_pConfigManager->getAnimationPropertyConfig("specialWorkspace") : g_pConfigManager->getAnimationPropertyConfig("workspaces"),
|
m_fAlpha.create(AVARTYPE_FLOAT, special ? g_pConfigManager->getAnimationPropertyConfig("specialWorkspace") : g_pConfigManager->getAnimationPropertyConfig("workspaces"),
|
||||||
nullptr, AVARDAMAGE_ENTIRE);
|
nullptr, AVARDAMAGE_ENTIRE);
|
||||||
|
@ -24,6 +24,10 @@ CWorkspace::CWorkspace(int monitorID, std::string name, bool special) {
|
||||||
m_vRenderOffset.registerVar();
|
m_vRenderOffset.registerVar();
|
||||||
m_fAlpha.registerVar();
|
m_fAlpha.registerVar();
|
||||||
|
|
||||||
|
const auto RULEFORTHIS = g_pConfigManager->getWorkspaceRuleFor(this);
|
||||||
|
if (RULEFORTHIS.defaultName.has_value())
|
||||||
|
m_szName = RULEFORTHIS.defaultName.value();
|
||||||
|
|
||||||
g_pEventManager->postEvent({"createworkspace", m_szName});
|
g_pEventManager->postEvent({"createworkspace", m_szName});
|
||||||
EMIT_HOOK_EVENT("createWorkspace", this);
|
EMIT_HOOK_EVENT("createWorkspace", this);
|
||||||
}
|
}
|
||||||
|
@ -38,8 +42,8 @@ CWorkspace::~CWorkspace() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void CWorkspace::startAnim(bool in, bool left, bool instant) {
|
void CWorkspace::startAnim(bool in, bool left, bool instant) {
|
||||||
const auto ANIMSTYLE = m_fAlpha.m_pConfig->pValues->internalStyle;
|
const auto ANIMSTYLE = m_fAlpha.m_pConfig->pValues->internalStyle;
|
||||||
const auto PWORKSPACEGAP = &g_pConfigManager->getConfigValuePtr("general:gaps_workspaces")->intValue;
|
static auto* const PWORKSPACEGAP = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("general:gaps_workspaces");
|
||||||
|
|
||||||
if (ANIMSTYLE.starts_with("slidefade")) {
|
if (ANIMSTYLE.starts_with("slidefade")) {
|
||||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
|
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
|
||||||
|
@ -91,7 +95,7 @@ void CWorkspace::startAnim(bool in, bool left, bool instant) {
|
||||||
} else if (ANIMSTYLE == "slidevert") {
|
} else if (ANIMSTYLE == "slidevert") {
|
||||||
// fallback is slide
|
// fallback is slide
|
||||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
|
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
|
||||||
const auto YDISTANCE = PMONITOR->vecSize.y + *PWORKSPACEGAP;
|
const auto YDISTANCE = PMONITOR->vecSize.y + **PWORKSPACEGAP;
|
||||||
|
|
||||||
m_fAlpha.setValueAndWarp(1.f); // fix a bug, if switching from fade -> slide.
|
m_fAlpha.setValueAndWarp(1.f); // fix a bug, if switching from fade -> slide.
|
||||||
|
|
||||||
|
@ -104,7 +108,7 @@ void CWorkspace::startAnim(bool in, bool left, bool instant) {
|
||||||
} else {
|
} else {
|
||||||
// fallback is slide
|
// fallback is slide
|
||||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
|
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
|
||||||
const auto XDISTANCE = PMONITOR->vecSize.x + *PWORKSPACEGAP;
|
const auto XDISTANCE = PMONITOR->vecSize.x + **PWORKSPACEGAP;
|
||||||
|
|
||||||
m_fAlpha.setValueAndWarp(1.f); // fix a bug, if switching from fade -> slide.
|
m_fAlpha.setValueAndWarp(1.f); // fix a bug, if switching from fade -> slide.
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "AnimatedVariable.hpp"
|
#include "../helpers/AnimatedVariable.hpp"
|
||||||
#include <string>
|
#include <string>
|
||||||
#include "../defines.hpp"
|
#include "../defines.hpp"
|
||||||
|
|
||||||
|
@ -35,9 +35,9 @@ class CWorkspace {
|
||||||
wl_array m_wlrCoordinateArr;
|
wl_array m_wlrCoordinateArr;
|
||||||
|
|
||||||
// for animations
|
// for animations
|
||||||
CAnimatedVariable m_vRenderOffset;
|
CAnimatedVariable<Vector2D> m_vRenderOffset;
|
||||||
CAnimatedVariable m_fAlpha;
|
CAnimatedVariable<float> m_fAlpha;
|
||||||
bool m_bForceRendering = false;
|
bool m_bForceRendering = false;
|
||||||
|
|
||||||
// "scratchpad"
|
// "scratchpad"
|
||||||
bool m_bIsSpecialWorkspace = false;
|
bool m_bIsSpecialWorkspace = false;
|
|
@ -22,25 +22,6 @@ namespace Events {
|
||||||
DYNLISTENFUNC(unmapLayerSurface);
|
DYNLISTENFUNC(unmapLayerSurface);
|
||||||
DYNLISTENFUNC(commitLayerSurface);
|
DYNLISTENFUNC(commitLayerSurface);
|
||||||
|
|
||||||
// Subsurfaces
|
|
||||||
DYNLISTENFUNC(newSubsurfaceNode);
|
|
||||||
DYNLISTENFUNC(destroySubsurfaceNode);
|
|
||||||
DYNLISTENFUNC(mapSubsurface);
|
|
||||||
DYNLISTENFUNC(unmapSubsurface);
|
|
||||||
DYNLISTENFUNC(destroySubsurface);
|
|
||||||
DYNLISTENFUNC(commitSubsurface);
|
|
||||||
|
|
||||||
// Popups
|
|
||||||
DYNLISTENFUNC(newPopup); // LayerSurface
|
|
||||||
|
|
||||||
DYNLISTENFUNC(newPopupXDG);
|
|
||||||
DYNLISTENFUNC(mapPopupXDG);
|
|
||||||
DYNLISTENFUNC(unmapPopupXDG);
|
|
||||||
DYNLISTENFUNC(destroyPopupXDG);
|
|
||||||
DYNLISTENFUNC(commitPopupXDG);
|
|
||||||
DYNLISTENFUNC(newPopupFromPopupXDG);
|
|
||||||
DYNLISTENFUNC(repositionPopupXDG);
|
|
||||||
|
|
||||||
// Surface XDG (window)
|
// Surface XDG (window)
|
||||||
LISTENER(newXDGToplevel);
|
LISTENER(newXDGToplevel);
|
||||||
LISTENER(activateXDG);
|
LISTENER(activateXDG);
|
||||||
|
@ -174,4 +155,7 @@ namespace Events {
|
||||||
|
|
||||||
// Tearing hints
|
// Tearing hints
|
||||||
LISTENER(newTearingHint);
|
LISTENER(newTearingHint);
|
||||||
|
|
||||||
|
// Shortcut inhibitor
|
||||||
|
LISTENER(newShortcutInhibitor);
|
||||||
};
|
};
|
||||||
|
|
|
@ -46,7 +46,6 @@ void Events::listener_newLayerSurface(wl_listener* listener, void* data) {
|
||||||
layerSurface->hyprListener_destroyLayerSurface.initCallback(&WLRLAYERSURFACE->events.destroy, &Events::listener_destroyLayerSurface, layerSurface, "layerSurface");
|
layerSurface->hyprListener_destroyLayerSurface.initCallback(&WLRLAYERSURFACE->events.destroy, &Events::listener_destroyLayerSurface, layerSurface, "layerSurface");
|
||||||
layerSurface->hyprListener_mapLayerSurface.initCallback(&WLRLAYERSURFACE->surface->events.map, &Events::listener_mapLayerSurface, layerSurface, "layerSurface");
|
layerSurface->hyprListener_mapLayerSurface.initCallback(&WLRLAYERSURFACE->surface->events.map, &Events::listener_mapLayerSurface, layerSurface, "layerSurface");
|
||||||
layerSurface->hyprListener_unmapLayerSurface.initCallback(&WLRLAYERSURFACE->surface->events.unmap, &Events::listener_unmapLayerSurface, layerSurface, "layerSurface");
|
layerSurface->hyprListener_unmapLayerSurface.initCallback(&WLRLAYERSURFACE->surface->events.unmap, &Events::listener_unmapLayerSurface, layerSurface, "layerSurface");
|
||||||
layerSurface->hyprListener_newPopup.initCallback(&WLRLAYERSURFACE->events.new_popup, &Events::listener_newPopup, layerSurface, "layerSurface");
|
|
||||||
|
|
||||||
layerSurface->layerSurface = WLRLAYERSURFACE;
|
layerSurface->layerSurface = WLRLAYERSURFACE;
|
||||||
layerSurface->layer = WLRLAYERSURFACE->current.layer;
|
layerSurface->layer = WLRLAYERSURFACE->current.layer;
|
||||||
|
@ -87,7 +86,6 @@ void Events::listener_destroyLayerSurface(void* owner, void* data) {
|
||||||
layersurface->hyprListener_destroyLayerSurface.removeCallback();
|
layersurface->hyprListener_destroyLayerSurface.removeCallback();
|
||||||
layersurface->hyprListener_mapLayerSurface.removeCallback();
|
layersurface->hyprListener_mapLayerSurface.removeCallback();
|
||||||
layersurface->hyprListener_unmapLayerSurface.removeCallback();
|
layersurface->hyprListener_unmapLayerSurface.removeCallback();
|
||||||
layersurface->hyprListener_newPopup.removeCallback();
|
|
||||||
|
|
||||||
// rearrange to fix the reserved areas
|
// rearrange to fix the reserved areas
|
||||||
if (PMONITOR) {
|
if (PMONITOR) {
|
||||||
|
@ -113,8 +111,7 @@ void Events::listener_mapLayerSurface(void* owner, void* data) {
|
||||||
layersurface->keyboardExclusive = layersurface->layerSurface->current.keyboard_interactive;
|
layersurface->keyboardExclusive = layersurface->layerSurface->current.keyboard_interactive;
|
||||||
layersurface->surface = layersurface->layerSurface->surface;
|
layersurface->surface = layersurface->layerSurface->surface;
|
||||||
|
|
||||||
// anim
|
layersurface->popupHead = std::make_unique<CPopup>(layersurface);
|
||||||
layersurface->alpha.setConfig(g_pConfigManager->getAnimationPropertyConfig("fadeIn"));
|
|
||||||
|
|
||||||
// fix if it changed its mon
|
// fix if it changed its mon
|
||||||
const auto PMONITOR = g_pCompositor->getMonitorFromOutput(layersurface->layerSurface->output);
|
const auto PMONITOR = g_pCompositor->getMonitorFromOutput(layersurface->layerSurface->output);
|
||||||
|
@ -142,6 +139,9 @@ void Events::listener_mapLayerSurface(void* owner, void* data) {
|
||||||
|
|
||||||
wlr_surface_send_enter(layersurface->layerSurface->surface, layersurface->layerSurface->output);
|
wlr_surface_send_enter(layersurface->layerSurface->surface, layersurface->layerSurface->output);
|
||||||
|
|
||||||
|
if (layersurface->layerSurface->current.keyboard_interactive == ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_EXCLUSIVE)
|
||||||
|
g_pInputManager->m_dExclusiveLSes.push_back(layersurface);
|
||||||
|
|
||||||
const bool GRABSFOCUS = layersurface->layerSurface->current.keyboard_interactive != ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_NONE &&
|
const bool GRABSFOCUS = layersurface->layerSurface->current.keyboard_interactive != ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_NONE &&
|
||||||
// don't focus if constrained
|
// don't focus if constrained
|
||||||
(!g_pCompositor->m_sSeat.mouse || !g_pCompositor->m_sSeat.mouse->currentConstraint);
|
(!g_pCompositor->m_sSeat.mouse || !g_pCompositor->m_sSeat.mouse->currentConstraint);
|
||||||
|
@ -163,8 +163,7 @@ void Events::listener_mapLayerSurface(void* owner, void* data) {
|
||||||
const auto WORKSPACE = g_pCompositor->getWorkspaceByID(PMONITOR->activeWorkspace);
|
const auto WORKSPACE = g_pCompositor->getWorkspaceByID(PMONITOR->activeWorkspace);
|
||||||
const bool FULLSCREEN = WORKSPACE->m_bHasFullscreenWindow && WORKSPACE->m_efFullscreenMode == FULLSCREEN_FULL;
|
const bool FULLSCREEN = WORKSPACE->m_bHasFullscreenWindow && WORKSPACE->m_efFullscreenMode == FULLSCREEN_FULL;
|
||||||
|
|
||||||
layersurface->alpha.setValue(0);
|
layersurface->startAnimation(!(layersurface->layer == ZWLR_LAYER_SHELL_V1_LAYER_TOP && FULLSCREEN && !GRABSFOCUS));
|
||||||
layersurface->alpha = ((layersurface->layer == ZWLR_LAYER_SHELL_V1_LAYER_TOP && FULLSCREEN && !GRABSFOCUS) ? 0.f : 1.f);
|
|
||||||
layersurface->readyToDelete = false;
|
layersurface->readyToDelete = false;
|
||||||
layersurface->fadingOut = false;
|
layersurface->fadingOut = false;
|
||||||
|
|
||||||
|
@ -183,6 +182,13 @@ void Events::listener_unmapLayerSurface(void* owner, void* data) {
|
||||||
g_pEventManager->postEvent(SHyprIPCEvent{"closelayer", std::string(layersurface->layerSurface->_namespace ? layersurface->layerSurface->_namespace : "")});
|
g_pEventManager->postEvent(SHyprIPCEvent{"closelayer", std::string(layersurface->layerSurface->_namespace ? layersurface->layerSurface->_namespace : "")});
|
||||||
EMIT_HOOK_EVENT("closeLayer", layersurface);
|
EMIT_HOOK_EVENT("closeLayer", layersurface);
|
||||||
|
|
||||||
|
std::erase(g_pInputManager->m_dExclusiveLSes, layersurface);
|
||||||
|
|
||||||
|
layersurface->popupHead.reset();
|
||||||
|
|
||||||
|
if (!g_pInputManager->m_dExclusiveLSes.empty())
|
||||||
|
g_pCompositor->focusSurface(g_pInputManager->m_dExclusiveLSes[0]->layerSurface->surface);
|
||||||
|
|
||||||
if (!g_pCompositor->getMonitorFromID(layersurface->monitorID) || g_pCompositor->m_bUnsafeState) {
|
if (!g_pCompositor->getMonitorFromID(layersurface->monitorID) || g_pCompositor->m_bUnsafeState) {
|
||||||
Debug::log(WARN, "Layersurface unmapping on invalid monitor (removed?) ignoring.");
|
Debug::log(WARN, "Layersurface unmapping on invalid monitor (removed?) ignoring.");
|
||||||
|
|
||||||
|
@ -190,23 +196,17 @@ void Events::listener_unmapLayerSurface(void* owner, void* data) {
|
||||||
|
|
||||||
layersurface->mapped = false;
|
layersurface->mapped = false;
|
||||||
|
|
||||||
layersurface->fadingOut = true;
|
layersurface->startAnimation(false);
|
||||||
|
|
||||||
layersurface->alpha.setValueAndWarp(0.f);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// anim
|
|
||||||
layersurface->alpha.setConfig(g_pConfigManager->getAnimationPropertyConfig("fadeOut"));
|
|
||||||
|
|
||||||
// make a snapshot and start fade
|
// make a snapshot and start fade
|
||||||
g_pHyprOpenGL->makeLayerSnapshot(layersurface);
|
g_pHyprOpenGL->makeLayerSnapshot(layersurface);
|
||||||
layersurface->alpha = 0.f;
|
|
||||||
|
layersurface->startAnimation(false);
|
||||||
|
|
||||||
layersurface->mapped = false;
|
layersurface->mapped = false;
|
||||||
|
|
||||||
layersurface->fadingOut = true;
|
|
||||||
|
|
||||||
g_pCompositor->addToFadingOutSafe(layersurface);
|
g_pCompositor->addToFadingOutSafe(layersurface);
|
||||||
|
|
||||||
const auto PMONITOR = g_pCompositor->getMonitorFromOutput(layersurface->layerSurface->output);
|
const auto PMONITOR = g_pCompositor->getMonitorFromOutput(layersurface->layerSurface->output);
|
||||||
|
@ -327,6 +327,19 @@ void Events::listener_commitLayerSurface(void* owner, void* data) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (layersurface->realPosition.goal() != layersurface->geometry.pos()) {
|
||||||
|
if (layersurface->realPosition.isBeingAnimated())
|
||||||
|
layersurface->realPosition = layersurface->geometry.pos();
|
||||||
|
else
|
||||||
|
layersurface->realPosition.setValueAndWarp(layersurface->geometry.pos());
|
||||||
|
}
|
||||||
|
if (layersurface->realSize.goal() != layersurface->geometry.size()) {
|
||||||
|
if (layersurface->realSize.isBeingAnimated())
|
||||||
|
layersurface->realSize = layersurface->geometry.size();
|
||||||
|
else
|
||||||
|
layersurface->realSize.setValueAndWarp(layersurface->geometry.size());
|
||||||
|
}
|
||||||
|
|
||||||
if (layersurface->layerSurface->current.keyboard_interactive &&
|
if (layersurface->layerSurface->current.keyboard_interactive &&
|
||||||
(!g_pCompositor->m_sSeat.mouse || !g_pCompositor->m_sSeat.mouse->currentConstraint) // don't focus if constrained
|
(!g_pCompositor->m_sSeat.mouse || !g_pCompositor->m_sSeat.mouse->currentConstraint) // don't focus if constrained
|
||||||
&& !layersurface->keyboardExclusive && layersurface->mapped) {
|
&& !layersurface->keyboardExclusive && layersurface->mapped) {
|
||||||
|
|
|
@ -128,6 +128,8 @@ void Events::listener_destroyDrag(void* owner, void* data) {
|
||||||
g_pInputManager->m_sDrag.drag = nullptr;
|
g_pInputManager->m_sDrag.drag = nullptr;
|
||||||
g_pInputManager->m_sDrag.dragIcon = nullptr;
|
g_pInputManager->m_sDrag.dragIcon = nullptr;
|
||||||
g_pInputManager->m_sDrag.hyprListener_destroy.removeCallback();
|
g_pInputManager->m_sDrag.hyprListener_destroy.removeCallback();
|
||||||
|
|
||||||
|
g_pCompositor->focusWindow(g_pCompositor->m_pLastWindow, g_pCompositor->m_pLastWindow ? g_pXWaylandManager->getWindowSurface(g_pCompositor->m_pLastWindow) : nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Events::listener_mapDragIcon(void* owner, void* data) {
|
void Events::listener_mapDragIcon(void* owner, void* data) {
|
||||||
|
@ -175,11 +177,17 @@ void Events::listener_sessionActive(wl_listener* listener, void* data) {
|
||||||
void Events::listener_powerMgrSetMode(wl_listener* listener, void* data) {
|
void Events::listener_powerMgrSetMode(wl_listener* listener, void* data) {
|
||||||
Debug::log(LOG, "PowerMgr set mode!");
|
Debug::log(LOG, "PowerMgr set mode!");
|
||||||
|
|
||||||
const auto EVENT = (wlr_output_power_v1_set_mode_event*)data;
|
const auto EVENT = (wlr_output_power_v1_set_mode_event*)data;
|
||||||
|
const auto PMONITOR = g_pCompositor->getMonitorFromOutput(EVENT->output);
|
||||||
|
|
||||||
wlr_output_enable(EVENT->output, EVENT->mode == 1);
|
if (!PMONITOR) {
|
||||||
|
Debug::log(ERR, "Invalid powerMgrSetMode output");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!wlr_output_commit(EVENT->output))
|
wlr_output_state_set_enabled(PMONITOR->state.wlr(), EVENT->mode == 1);
|
||||||
|
|
||||||
|
if (!PMONITOR->state.commit())
|
||||||
Debug::log(ERR, "Couldn't set power mode");
|
Debug::log(ERR, "Couldn't set power mode");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -225,16 +233,7 @@ void Events::listener_setCursorShape(wl_listener* listener, void* data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Events::listener_newTearingHint(wl_listener* listener, void* data) {
|
void Events::listener_newTearingHint(wl_listener* listener, void* data) {
|
||||||
const auto TCTL = (wlr_tearing_control_v1*)data;
|
Debug::log(LOG, "New tearing hint at {:x}", (uintptr_t)data);
|
||||||
|
|
||||||
const auto PWINDOW = g_pCompositor->getWindowFromSurface(TCTL->surface);
|
|
||||||
|
|
||||||
if (!PWINDOW) {
|
|
||||||
Debug::log(ERR, "Tearing hint {} was attached to an unknown surface", (uintptr_t)data);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Debug::log(LOG, "New tearing hint for window {} at {}", PWINDOW, (uintptr_t)data);
|
|
||||||
|
|
||||||
const auto NEWCTRL = g_pHyprRenderer->m_vTearingControllers.emplace_back(std::make_unique<STearingController>()).get();
|
const auto NEWCTRL = g_pHyprRenderer->m_vTearingControllers.emplace_back(std::make_unique<STearingController>()).get();
|
||||||
NEWCTRL->pWlrHint = (wlr_tearing_control_v1*)data;
|
NEWCTRL->pWlrHint = (wlr_tearing_control_v1*)data;
|
||||||
|
@ -242,7 +241,7 @@ void Events::listener_newTearingHint(wl_listener* listener, void* data) {
|
||||||
NEWCTRL->hyprListener_destroy.initCallback(
|
NEWCTRL->hyprListener_destroy.initCallback(
|
||||||
&NEWCTRL->pWlrHint->events.destroy,
|
&NEWCTRL->pWlrHint->events.destroy,
|
||||||
[&](void* owner, void* data) {
|
[&](void* owner, void* data) {
|
||||||
Debug::log(LOG, "Destroyed {} tearing hint", (uintptr_t)((STearingController*)owner)->pWlrHint);
|
Debug::log(LOG, "Destroyed {:x} tearing hint", (uintptr_t)((STearingController*)owner)->pWlrHint);
|
||||||
|
|
||||||
std::erase_if(g_pHyprRenderer->m_vTearingControllers, [&](const auto& other) { return other.get() == owner; });
|
std::erase_if(g_pHyprRenderer->m_vTearingControllers, [&](const auto& other) { return other.get() == owner; });
|
||||||
},
|
},
|
||||||
|
@ -256,10 +255,27 @@ void Events::listener_newTearingHint(wl_listener* listener, void* data) {
|
||||||
const auto PWINDOW = g_pCompositor->getWindowFromSurface(TEARINGHINT->pWlrHint->surface);
|
const auto PWINDOW = g_pCompositor->getWindowFromSurface(TEARINGHINT->pWlrHint->surface);
|
||||||
|
|
||||||
if (PWINDOW) {
|
if (PWINDOW) {
|
||||||
PWINDOW->m_bTearingHint = TEARINGHINT->pWlrHint->hint;
|
PWINDOW->m_bTearingHint = (bool)TEARINGHINT->pWlrHint->current;
|
||||||
|
|
||||||
Debug::log(LOG, "Hint {} (window {}) set tearing hint to {}", (uintptr_t)TEARINGHINT->pWlrHint, PWINDOW, (uint32_t)TEARINGHINT->pWlrHint->hint);
|
Debug::log(LOG, "Hint {:x} (window {}) set tearing hint to {}", (uintptr_t)TEARINGHINT->pWlrHint, PWINDOW, (uint32_t)TEARINGHINT->pWlrHint->current);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
NEWCTRL, "TearingController");
|
NEWCTRL, "TearingController");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Events::listener_newShortcutInhibitor(wl_listener* listener, void* data) {
|
||||||
|
const auto INHIBITOR = (wlr_keyboard_shortcuts_inhibitor_v1*)data;
|
||||||
|
|
||||||
|
const auto PINH = &g_pKeybindManager->m_lShortcutInhibitors.emplace_back();
|
||||||
|
PINH->hyprListener_destroy.initCallback(
|
||||||
|
&INHIBITOR->events.destroy,
|
||||||
|
[](void* owner, void* data) {
|
||||||
|
const auto OWNER = (SShortcutInhibitor*)owner;
|
||||||
|
g_pKeybindManager->m_lShortcutInhibitors.remove(*OWNER);
|
||||||
|
},
|
||||||
|
PINH, "ShortcutInhibitor");
|
||||||
|
|
||||||
|
PINH->pWlrInhibitor = INHIBITOR;
|
||||||
|
|
||||||
|
Debug::log(LOG, "New shortcut inhibitor for surface {:x}", (uintptr_t)INHIBITOR->surface);
|
||||||
|
}
|
||||||
|
|
|
@ -109,7 +109,7 @@ void Events::listener_newOutput(wl_listener* listener, void* data) {
|
||||||
for (auto& w : g_pCompositor->m_vWindows) {
|
for (auto& w : g_pCompositor->m_vWindows) {
|
||||||
if (w->m_iMonitorID == PNEWMONITOR->ID) {
|
if (w->m_iMonitorID == PNEWMONITOR->ID) {
|
||||||
w->m_iLastSurfaceMonitorID = -1;
|
w->m_iLastSurfaceMonitorID = -1;
|
||||||
w->updateSurfaceOutputs();
|
w->updateSurfaceScaleTransformDetails();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -147,12 +147,12 @@ void Events::listener_monitorFrame(void* owner, void* data) {
|
||||||
PMONITOR->tearingState.frameScheduledWhileBusy = false;
|
PMONITOR->tearingState.frameScheduledWhileBusy = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static auto* const PENABLERAT = &g_pConfigManager->getConfigValuePtr("misc:render_ahead_of_time")->intValue;
|
static auto* const PENABLERAT = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("misc:render_ahead_of_time");
|
||||||
static auto* const PRATSAFE = &g_pConfigManager->getConfigValuePtr("misc:render_ahead_safezone")->intValue;
|
static auto* const PRATSAFE = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("misc:render_ahead_safezone");
|
||||||
|
|
||||||
PMONITOR->lastPresentationTimer.reset();
|
PMONITOR->lastPresentationTimer.reset();
|
||||||
|
|
||||||
if (*PENABLERAT && !PMONITOR->tearingState.nextRenderTorn) {
|
if (**PENABLERAT && !PMONITOR->tearingState.nextRenderTorn) {
|
||||||
if (!PMONITOR->RATScheduled) {
|
if (!PMONITOR->RATScheduled) {
|
||||||
// render
|
// render
|
||||||
g_pHyprRenderer->renderMonitor(PMONITOR);
|
g_pHyprRenderer->renderMonitor(PMONITOR);
|
||||||
|
@ -162,14 +162,14 @@ void Events::listener_monitorFrame(void* owner, void* data) {
|
||||||
|
|
||||||
const auto& [avg, max, min] = g_pHyprRenderer->getRenderTimes(PMONITOR);
|
const auto& [avg, max, min] = g_pHyprRenderer->getRenderTimes(PMONITOR);
|
||||||
|
|
||||||
if (max + *PRATSAFE > 1000.0 / PMONITOR->refreshRate)
|
if (max + **PRATSAFE > 1000.0 / PMONITOR->refreshRate)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const auto MSLEFT = 1000.0 / PMONITOR->refreshRate - PMONITOR->lastPresentationTimer.getMillis();
|
const auto MSLEFT = 1000.0 / PMONITOR->refreshRate - PMONITOR->lastPresentationTimer.getMillis();
|
||||||
|
|
||||||
PMONITOR->RATScheduled = true;
|
PMONITOR->RATScheduled = true;
|
||||||
|
|
||||||
const auto ESTRENDERTIME = std::ceil(avg + *PRATSAFE);
|
const auto ESTRENDERTIME = std::ceil(avg + **PRATSAFE);
|
||||||
const auto TIMETOSLEEP = std::floor(MSLEFT - ESTRENDERTIME);
|
const auto TIMETOSLEEP = std::floor(MSLEFT - ESTRENDERTIME);
|
||||||
|
|
||||||
if (MSLEFT < 1 || MSLEFT < ESTRENDERTIME || TIMETOSLEEP < 1)
|
if (MSLEFT < 1 || MSLEFT < ESTRENDERTIME || TIMETOSLEEP < 1)
|
||||||
|
@ -212,7 +212,17 @@ void Events::listener_monitorStateRequest(void* owner, void* data) {
|
||||||
const auto PMONITOR = (CMonitor*)owner;
|
const auto PMONITOR = (CMonitor*)owner;
|
||||||
const auto E = (wlr_output_event_request_state*)data;
|
const auto E = (wlr_output_event_request_state*)data;
|
||||||
|
|
||||||
wlr_output_commit_state(PMONITOR->output, E->state);
|
if (!PMONITOR->createdByUser)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const auto SIZE = E->state->mode ? Vector2D{E->state->mode->width, E->state->mode->height} : Vector2D{E->state->custom_mode.width, E->state->custom_mode.height};
|
||||||
|
|
||||||
|
PMONITOR->forceSize = SIZE;
|
||||||
|
|
||||||
|
SMonitorRule rule = PMONITOR->activeMonitorRule;
|
||||||
|
rule.resolution = SIZE;
|
||||||
|
|
||||||
|
g_pHyprRenderer->applyMonitorRule(PMONITOR, &rule);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Events::listener_monitorDamage(void* owner, void* data) {
|
void Events::listener_monitorDamage(void* owner, void* data) {
|
||||||
|
|
|
@ -1,264 +0,0 @@
|
||||||
#include "Events.hpp"
|
|
||||||
|
|
||||||
#include "../Compositor.hpp"
|
|
||||||
#include "../helpers/WLClasses.hpp"
|
|
||||||
#include "../managers/input/InputManager.hpp"
|
|
||||||
#include "../render/Renderer.hpp"
|
|
||||||
|
|
||||||
// --------------------------------------------- //
|
|
||||||
// _____ ____ _____ _ _ _____ _____ //
|
|
||||||
// | __ \ / __ \| __ \| | | | __ \ / ____| //
|
|
||||||
// | |__) | | | | |__) | | | | |__) | (___ //
|
|
||||||
// | ___/| | | | ___/| | | | ___/ \___ \ //
|
|
||||||
// | | | |__| | | | |__| | | ____) | //
|
|
||||||
// |_| \____/|_| \____/|_| |_____/ //
|
|
||||||
// //
|
|
||||||
// --------------------------------------------- //
|
|
||||||
|
|
||||||
void addPopupGlobalCoords(void* pPopup, int* x, int* y) {
|
|
||||||
SXDGPopup* const PPOPUP = (SXDGPopup*)pPopup;
|
|
||||||
|
|
||||||
auto curPopup = PPOPUP;
|
|
||||||
|
|
||||||
int px = 0;
|
|
||||||
int py = 0;
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
px += curPopup->popup->current.geometry.x;
|
|
||||||
py += curPopup->popup->current.geometry.y;
|
|
||||||
|
|
||||||
if (curPopup == PPOPUP && PPOPUP->parentWindow) {
|
|
||||||
px -= curPopup->popup->base->current.geometry.x;
|
|
||||||
py -= curPopup->popup->base->current.geometry.y;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (curPopup->popup && !curPopup->parentPopup && !curPopup->parentWindow) {
|
|
||||||
const auto EXTENTSSURFACE = pixman_region32_extents(&curPopup->popup->base->surface->input_region);
|
|
||||||
px -= EXTENTSSURFACE->x1;
|
|
||||||
py -= EXTENTSSURFACE->y1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (curPopup->parentPopup) {
|
|
||||||
curPopup = curPopup->parentPopup;
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
px += PPOPUP->lx;
|
|
||||||
py += PPOPUP->ly;
|
|
||||||
|
|
||||||
*x += px;
|
|
||||||
*y += py;
|
|
||||||
}
|
|
||||||
|
|
||||||
void createNewPopup(wlr_xdg_popup* popup, SXDGPopup* pHyprPopup) {
|
|
||||||
pHyprPopup->popup = popup;
|
|
||||||
|
|
||||||
pHyprPopup->hyprListener_destroyPopupXDG.initCallback(&popup->base->events.destroy, &Events::listener_destroyPopupXDG, pHyprPopup, "HyprPopup");
|
|
||||||
pHyprPopup->hyprListener_mapPopupXDG.initCallback(&popup->base->surface->events.map, &Events::listener_mapPopupXDG, pHyprPopup, "HyprPopup");
|
|
||||||
pHyprPopup->hyprListener_unmapPopupXDG.initCallback(&popup->base->surface->events.unmap, &Events::listener_unmapPopupXDG, pHyprPopup, "HyprPopup");
|
|
||||||
pHyprPopup->hyprListener_newPopupFromPopupXDG.initCallback(&popup->base->events.new_popup, &Events::listener_newPopupFromPopupXDG, pHyprPopup, "HyprPopup");
|
|
||||||
pHyprPopup->hyprListener_commitPopupXDG.initCallback(&popup->base->surface->events.commit, &Events::listener_commitPopupXDG, pHyprPopup, "HyprPopup");
|
|
||||||
pHyprPopup->hyprListener_repositionPopupXDG.initCallback(&popup->events.reposition, &Events::listener_repositionPopupXDG, pHyprPopup, "HyprPopup");
|
|
||||||
|
|
||||||
const auto PMONITOR = g_pCompositor->m_pLastMonitor;
|
|
||||||
|
|
||||||
CBox box = {PMONITOR->vecPosition.x - pHyprPopup->lx, PMONITOR->vecPosition.y - pHyprPopup->ly, PMONITOR->vecSize.x, PMONITOR->vecSize.y};
|
|
||||||
|
|
||||||
wlr_xdg_popup_unconstrain_from_box(popup, box.pWlr());
|
|
||||||
|
|
||||||
pHyprPopup->monitor = PMONITOR;
|
|
||||||
|
|
||||||
Debug::log(LOG, "Popup: Unconstrained from lx ly: {:j5}, pHyprPopup lx ly: {:.5f} {:.5f}", PMONITOR->vecPosition, (float)pHyprPopup->lx, (float)pHyprPopup->ly);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Events::listener_newPopup(void* owner, void* data) {
|
|
||||||
SLayerSurface* layersurface = (SLayerSurface*)owner;
|
|
||||||
|
|
||||||
ASSERT(layersurface);
|
|
||||||
|
|
||||||
Debug::log(LOG, "New layer popup created from surface {:x}", (uintptr_t)layersurface);
|
|
||||||
|
|
||||||
const auto WLRPOPUP = (wlr_xdg_popup*)data;
|
|
||||||
|
|
||||||
const auto PNEWPOPUP = g_pCompositor->m_vXDGPopups.emplace_back(std::make_unique<SXDGPopup>()).get();
|
|
||||||
|
|
||||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(layersurface->monitorID);
|
|
||||||
|
|
||||||
PNEWPOPUP->popup = WLRPOPUP;
|
|
||||||
PNEWPOPUP->lx = layersurface->position.x;
|
|
||||||
PNEWPOPUP->ly = layersurface->position.y;
|
|
||||||
PNEWPOPUP->monitor = PMONITOR;
|
|
||||||
PNEWPOPUP->parentLS = layersurface;
|
|
||||||
createNewPopup(WLRPOPUP, PNEWPOPUP);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Events::listener_newPopupXDG(void* owner, void* data) {
|
|
||||||
CWindow* PWINDOW = (CWindow*)owner;
|
|
||||||
|
|
||||||
ASSERT(PWINDOW);
|
|
||||||
|
|
||||||
if (!PWINDOW->m_bIsMapped)
|
|
||||||
return;
|
|
||||||
|
|
||||||
Debug::log(LOG, "New layer popup created from XDG window {}", PWINDOW);
|
|
||||||
|
|
||||||
const auto WLRPOPUP = (wlr_xdg_popup*)data;
|
|
||||||
|
|
||||||
const auto PNEWPOPUP = g_pCompositor->m_vXDGPopups.emplace_back(std::make_unique<SXDGPopup>()).get();
|
|
||||||
|
|
||||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID);
|
|
||||||
|
|
||||||
PNEWPOPUP->popup = WLRPOPUP;
|
|
||||||
PNEWPOPUP->lx = PWINDOW->m_vRealPosition.goalv().x;
|
|
||||||
PNEWPOPUP->ly = PWINDOW->m_vRealPosition.goalv().y;
|
|
||||||
PNEWPOPUP->parentWindow = PWINDOW;
|
|
||||||
PNEWPOPUP->monitor = PMONITOR;
|
|
||||||
createNewPopup(WLRPOPUP, PNEWPOPUP);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Events::listener_newPopupFromPopupXDG(void* owner, void* data) {
|
|
||||||
SXDGPopup* PPOPUP = (SXDGPopup*)owner;
|
|
||||||
|
|
||||||
ASSERT(PPOPUP);
|
|
||||||
|
|
||||||
if (PPOPUP->parentWindow)
|
|
||||||
Debug::log(LOG, "New popup created from XDG Window popup {:x} -> {}", (uintptr_t)PPOPUP, PPOPUP->parentWindow);
|
|
||||||
else
|
|
||||||
Debug::log(LOG, "New popup created from Non-Window popup {:x}", (uintptr_t)PPOPUP);
|
|
||||||
|
|
||||||
const auto WLRPOPUP = (wlr_xdg_popup*)data;
|
|
||||||
|
|
||||||
const auto PNEWPOPUP = g_pCompositor->m_vXDGPopups.emplace_back(std::make_unique<SXDGPopup>()).get();
|
|
||||||
|
|
||||||
PNEWPOPUP->popup = WLRPOPUP;
|
|
||||||
PNEWPOPUP->parentPopup = PPOPUP;
|
|
||||||
PNEWPOPUP->lx = PPOPUP->lx;
|
|
||||||
PNEWPOPUP->ly = PPOPUP->ly;
|
|
||||||
PNEWPOPUP->parentWindow = PPOPUP->parentWindow;
|
|
||||||
PNEWPOPUP->monitor = PPOPUP->monitor;
|
|
||||||
|
|
||||||
createNewPopup(WLRPOPUP, PNEWPOPUP);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Events::listener_mapPopupXDG(void* owner, void* data) {
|
|
||||||
SXDGPopup* PPOPUP = (SXDGPopup*)owner;
|
|
||||||
|
|
||||||
ASSERT(PPOPUP);
|
|
||||||
|
|
||||||
Debug::log(LOG, "New XDG Popup mapped at {} {}", (int)PPOPUP->lx, (int)PPOPUP->ly);
|
|
||||||
|
|
||||||
if (PPOPUP->parentWindow)
|
|
||||||
PPOPUP->parentWindow->m_lPopupSurfaces.emplace_back(PPOPUP->popup->base->surface);
|
|
||||||
else if (PPOPUP->parentLS)
|
|
||||||
PPOPUP->parentLS->popupSurfaces.emplace_back(PPOPUP->popup->base->surface);
|
|
||||||
|
|
||||||
PPOPUP->pSurfaceTree = SubsurfaceTree::createTreeRoot(PPOPUP->popup->base->surface, addPopupGlobalCoords, PPOPUP, PPOPUP->parentWindow);
|
|
||||||
|
|
||||||
int lx = 0, ly = 0;
|
|
||||||
addPopupGlobalCoords(PPOPUP, &lx, &ly);
|
|
||||||
|
|
||||||
CBox extents;
|
|
||||||
wlr_surface_get_extends(PPOPUP->popup->base->surface, extents.pWlr());
|
|
||||||
extents.applyFromWlr();
|
|
||||||
|
|
||||||
g_pHyprRenderer->damageBox(lx - extents.x, ly - extents.y, extents.width + 2, extents.height + 2);
|
|
||||||
|
|
||||||
if (PPOPUP->monitor) {
|
|
||||||
g_pCompositor->setPreferredScaleForSurface(PPOPUP->popup->base->surface, PPOPUP->monitor->scale);
|
|
||||||
g_pCompositor->setPreferredTransformForSurface(PPOPUP->popup->base->surface, PPOPUP->monitor->transform);
|
|
||||||
}
|
|
||||||
|
|
||||||
Debug::log(LOG, "XDG Popup got assigned a surfaceTreeNode {:x}", (uintptr_t)PPOPUP->pSurfaceTree);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Events::listener_repositionPopupXDG(void* owner, void* data) {
|
|
||||||
SXDGPopup* PPOPUP = (SXDGPopup*)owner;
|
|
||||||
|
|
||||||
Debug::log(LOG, "XDG Popup {:x} asks for a reposition", (uintptr_t)PPOPUP);
|
|
||||||
|
|
||||||
int lx = 0, ly = 0;
|
|
||||||
addPopupGlobalCoords(PPOPUP, &lx, &ly);
|
|
||||||
|
|
||||||
CBox extents;
|
|
||||||
wlr_surface_get_extends(PPOPUP->popup->base->surface, extents.pWlr());
|
|
||||||
extents.applyFromWlr();
|
|
||||||
|
|
||||||
PPOPUP->lastPos = {lx - extents.x, ly - extents.y};
|
|
||||||
PPOPUP->repositionRequested = true;
|
|
||||||
|
|
||||||
const auto PMONITOR = g_pCompositor->m_pLastMonitor;
|
|
||||||
|
|
||||||
CBox box = {PMONITOR->vecPosition.x - lx + PPOPUP->popup->current.geometry.x, PMONITOR->vecPosition.y - ly + PPOPUP->popup->current.geometry.y, PMONITOR->vecSize.x,
|
|
||||||
PMONITOR->vecSize.y};
|
|
||||||
wlr_xdg_popup_unconstrain_from_box(PPOPUP->popup, box.pWlr());
|
|
||||||
}
|
|
||||||
|
|
||||||
void Events::listener_unmapPopupXDG(void* owner, void* data) {
|
|
||||||
SXDGPopup* PPOPUP = (SXDGPopup*)owner;
|
|
||||||
Debug::log(LOG, "XDG Popup unmapped");
|
|
||||||
|
|
||||||
ASSERT(PPOPUP);
|
|
||||||
|
|
||||||
if (PPOPUP->popup->base->surface == g_pCompositor->m_pLastFocus)
|
|
||||||
g_pInputManager->releaseAllMouseButtons();
|
|
||||||
|
|
||||||
SubsurfaceTree::destroySurfaceTree(PPOPUP->pSurfaceTree);
|
|
||||||
|
|
||||||
int lx = 0, ly = 0;
|
|
||||||
addPopupGlobalCoords(PPOPUP, &lx, &ly);
|
|
||||||
|
|
||||||
CBox extents;
|
|
||||||
wlr_surface_get_extends(PPOPUP->popup->base->surface, extents.pWlr());
|
|
||||||
extents.applyFromWlr();
|
|
||||||
|
|
||||||
g_pHyprRenderer->damageBox(lx - extents.x, ly - extents.y, extents.width + 2, extents.height + 2);
|
|
||||||
|
|
||||||
if (PPOPUP->parentWindow)
|
|
||||||
std::erase(PPOPUP->parentWindow->m_lPopupSurfaces, PPOPUP->popup->base->surface);
|
|
||||||
else if (PPOPUP->parentLS)
|
|
||||||
std::erase(PPOPUP->parentLS->popupSurfaces, PPOPUP->popup->base->surface);
|
|
||||||
|
|
||||||
PPOPUP->pSurfaceTree = nullptr;
|
|
||||||
|
|
||||||
g_pInputManager->simulateMouseMovement(); // to focus and return back to an appropriate surface
|
|
||||||
}
|
|
||||||
|
|
||||||
void Events::listener_commitPopupXDG(void* owner, void* data) {
|
|
||||||
SXDGPopup* PPOPUP = (SXDGPopup*)owner;
|
|
||||||
|
|
||||||
if (g_pCompositor->windowValidMapped(PPOPUP->parentWindow)) {
|
|
||||||
PPOPUP->lx = PPOPUP->parentWindow->m_vRealPosition.vec().x;
|
|
||||||
PPOPUP->ly = PPOPUP->parentWindow->m_vRealPosition.vec().y;
|
|
||||||
}
|
|
||||||
|
|
||||||
int lx = 0, ly = 0;
|
|
||||||
addPopupGlobalCoords(PPOPUP, &lx, &ly);
|
|
||||||
|
|
||||||
CBox extents;
|
|
||||||
wlr_surface_get_extends(PPOPUP->popup->base->surface, extents.pWlr());
|
|
||||||
extents.applyFromWlr();
|
|
||||||
|
|
||||||
if (PPOPUP->repositionRequested)
|
|
||||||
g_pHyprRenderer->damageBox(PPOPUP->lastPos.x, PPOPUP->lastPos.y, extents.width + 2, extents.height + 2);
|
|
||||||
|
|
||||||
PPOPUP->repositionRequested = false;
|
|
||||||
|
|
||||||
g_pHyprRenderer->damageSurface(PPOPUP->popup->base->surface, lx, ly);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Events::listener_destroyPopupXDG(void* owner, void* data) {
|
|
||||||
SXDGPopup* PPOPUP = (SXDGPopup*)owner;
|
|
||||||
|
|
||||||
ASSERT(PPOPUP);
|
|
||||||
|
|
||||||
Debug::log(LOG, "Destroyed popup XDG {:x}", (uintptr_t)PPOPUP);
|
|
||||||
|
|
||||||
if (PPOPUP->pSurfaceTree) {
|
|
||||||
SubsurfaceTree::destroySurfaceTree(PPOPUP->pSurfaceTree);
|
|
||||||
PPOPUP->pSurfaceTree = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::erase_if(g_pCompositor->m_vXDGPopups, [&](std::unique_ptr<SXDGPopup>& el) { return el.get() == PPOPUP; });
|
|
||||||
}
|
|
|
@ -17,8 +17,8 @@
|
||||||
|
|
||||||
void addViewCoords(void* pWindow, int* x, int* y) {
|
void addViewCoords(void* pWindow, int* x, int* y) {
|
||||||
const auto PWINDOW = (CWindow*)pWindow;
|
const auto PWINDOW = (CWindow*)pWindow;
|
||||||
*x += PWINDOW->m_vRealPosition.goalv().x;
|
*x += PWINDOW->m_vRealPosition.goal().x;
|
||||||
*y += PWINDOW->m_vRealPosition.goalv().y;
|
*y += PWINDOW->m_vRealPosition.goal().y;
|
||||||
|
|
||||||
if (!PWINDOW->m_bIsX11 && PWINDOW->m_bIsMapped) {
|
if (!PWINDOW->m_bIsX11 && PWINDOW->m_bIsMapped) {
|
||||||
wlr_box geom;
|
wlr_box geom;
|
||||||
|
@ -30,9 +30,9 @@ void addViewCoords(void* pWindow, int* x, int* y) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void setAnimToMove(void* data) {
|
void setAnimToMove(void* data) {
|
||||||
auto* const PANIMCFG = g_pConfigManager->getAnimationPropertyConfig("windowsMove");
|
auto* const PANIMCFG = g_pConfigManager->getAnimationPropertyConfig("windowsMove");
|
||||||
|
|
||||||
CAnimatedVariable* animvar = (CAnimatedVariable*)data;
|
CBaseAnimatedVariable* animvar = (CBaseAnimatedVariable*)data;
|
||||||
|
|
||||||
animvar->setConfig(PANIMCFG);
|
animvar->setConfig(PANIMCFG);
|
||||||
}
|
}
|
||||||
|
@ -40,17 +40,16 @@ void setAnimToMove(void* data) {
|
||||||
void Events::listener_mapWindow(void* owner, void* data) {
|
void Events::listener_mapWindow(void* owner, void* data) {
|
||||||
CWindow* PWINDOW = (CWindow*)owner;
|
CWindow* PWINDOW = (CWindow*)owner;
|
||||||
|
|
||||||
static auto* const PINACTIVEALPHA = &g_pConfigManager->getConfigValuePtr("decoration:inactive_opacity")->floatValue;
|
static auto* const PINACTIVEALPHA = (Hyprlang::FLOAT* const*)g_pConfigManager->getConfigValuePtr("decoration:inactive_opacity");
|
||||||
static auto* const PACTIVEALPHA = &g_pConfigManager->getConfigValuePtr("decoration:active_opacity")->floatValue;
|
static auto* const PACTIVEALPHA = (Hyprlang::FLOAT* const*)g_pConfigManager->getConfigValuePtr("decoration:active_opacity");
|
||||||
static auto* const PDIMSTRENGTH = &g_pConfigManager->getConfigValuePtr("decoration:dim_strength")->floatValue;
|
static auto* const PDIMSTRENGTH = (Hyprlang::FLOAT* const*)g_pConfigManager->getConfigValuePtr("decoration:dim_strength");
|
||||||
static auto* const PSWALLOW = &g_pConfigManager->getConfigValuePtr("misc:enable_swallow")->intValue;
|
static auto* const PSWALLOW = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("misc:enable_swallow");
|
||||||
static auto* const PSWALLOWREGEX = &g_pConfigManager->getConfigValuePtr("misc:swallow_regex")->strValue;
|
static auto* const PSWALLOWREGEX = (Hyprlang::STRING const*)g_pConfigManager->getConfigValuePtr("misc:swallow_regex");
|
||||||
static auto* const PSWALLOWEXREGEX = &g_pConfigManager->getConfigValuePtr("misc:swallow_exception_regex")->strValue;
|
static auto* const PSWALLOWEXREGEX = (Hyprlang::STRING const*)g_pConfigManager->getConfigValuePtr("misc:swallow_exception_regex");
|
||||||
static auto* const PNEWTAKESOVERFS = &g_pConfigManager->getConfigValuePtr("misc:new_window_takes_over_fullscreen")->intValue;
|
static auto* const PNEWTAKESOVERFS = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("misc:new_window_takes_over_fullscreen");
|
||||||
|
|
||||||
auto PMONITOR = g_pCompositor->m_pLastMonitor;
|
auto PMONITOR = g_pCompositor->m_pLastMonitor;
|
||||||
const auto PWORKSPACE =
|
auto PWORKSPACE = PMONITOR->specialWorkspaceID ? g_pCompositor->getWorkspaceByID(PMONITOR->specialWorkspaceID) : g_pCompositor->getWorkspaceByID(PMONITOR->activeWorkspace);
|
||||||
PMONITOR->specialWorkspaceID ? g_pCompositor->getWorkspaceByID(PMONITOR->specialWorkspaceID) : g_pCompositor->getWorkspaceByID(PMONITOR->activeWorkspace);
|
|
||||||
PWINDOW->m_iMonitorID = PMONITOR->ID;
|
PWINDOW->m_iMonitorID = PMONITOR->ID;
|
||||||
PWINDOW->m_iWorkspaceID = PMONITOR->specialWorkspaceID ? PMONITOR->specialWorkspaceID : PMONITOR->activeWorkspace;
|
PWINDOW->m_iWorkspaceID = PMONITOR->specialWorkspaceID ? PMONITOR->specialWorkspaceID : PMONITOR->activeWorkspace;
|
||||||
PWINDOW->m_bIsMapped = true;
|
PWINDOW->m_bIsMapped = true;
|
||||||
|
@ -101,7 +100,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// window rules
|
// window rules
|
||||||
const auto WINDOWRULES = g_pConfigManager->getMatchingRules(PWINDOW);
|
const auto WINDOWRULES = g_pConfigManager->getMatchingRules(PWINDOW, false);
|
||||||
std::string requestedWorkspace = "";
|
std::string requestedWorkspace = "";
|
||||||
bool workspaceSilent = false;
|
bool workspaceSilent = false;
|
||||||
bool requestsFullscreen = PWINDOW->m_bWantsInitialFullscreen ||
|
bool requestsFullscreen = PWINDOW->m_bWantsInitialFullscreen ||
|
||||||
|
@ -173,13 +172,23 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||||
} else if (r.szRule.starts_with("pseudo")) {
|
} else if (r.szRule.starts_with("pseudo")) {
|
||||||
PWINDOW->m_bIsPseudotiled = true;
|
PWINDOW->m_bIsPseudotiled = true;
|
||||||
} else if (r.szRule.starts_with("nofocus")) {
|
} else if (r.szRule.starts_with("nofocus")) {
|
||||||
PWINDOW->m_bNoFocus = true;
|
PWINDOW->m_sAdditionalConfigData.noFocus = true;
|
||||||
} else if (r.szRule.starts_with("noinitialfocus")) {
|
} else if (r.szRule.starts_with("noinitialfocus")) {
|
||||||
PWINDOW->m_bNoInitialFocus = true;
|
PWINDOW->m_bNoInitialFocus = true;
|
||||||
} else if (r.szRule.starts_with("nofullscreenrequest")) {
|
} else if (r.szRule.starts_with("suppressevent")) {
|
||||||
PWINDOW->m_bNoFullscreenRequest = true;
|
CVarList vars(r.szRule, 0, 's', true);
|
||||||
} else if (r.szRule.starts_with("nomaximizerequest")) {
|
for (size_t i = 1; i < vars.size(); ++i) {
|
||||||
PWINDOW->m_bNoMaximizeRequest = true;
|
if (vars[i] == "fullscreen")
|
||||||
|
PWINDOW->m_eSuppressedEvents |= SUPPRESS_FULLSCREEN;
|
||||||
|
else if (vars[i] == "maximize")
|
||||||
|
PWINDOW->m_eSuppressedEvents |= SUPPRESS_MAXIMIZE;
|
||||||
|
else if (vars[i] == "activate")
|
||||||
|
PWINDOW->m_eSuppressedEvents |= SUPPRESS_ACTIVATE;
|
||||||
|
else if (vars[i] == "activatefocus")
|
||||||
|
PWINDOW->m_eSuppressedEvents |= SUPPRESS_ACTIVATE_FOCUSONLY;
|
||||||
|
else
|
||||||
|
Debug::log(ERR, "Error while parsing suppressevent windowrule: unknown event type {}", vars[i]);
|
||||||
|
}
|
||||||
} else if (r.szRule == "fullscreen") {
|
} else if (r.szRule == "fullscreen") {
|
||||||
requestsFullscreen = true;
|
requestsFullscreen = true;
|
||||||
overridingNoFullscreen = true;
|
overridingNoFullscreen = true;
|
||||||
|
@ -270,6 +279,8 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||||
if (!pWorkspace)
|
if (!pWorkspace)
|
||||||
pWorkspace = g_pCompositor->createNewWorkspace(REQUESTEDWORKSPACEID, PWINDOW->m_iMonitorID, requestedWorkspaceName);
|
pWorkspace = g_pCompositor->createNewWorkspace(REQUESTEDWORKSPACEID, PWINDOW->m_iMonitorID, requestedWorkspaceName);
|
||||||
|
|
||||||
|
PWORKSPACE = pWorkspace;
|
||||||
|
|
||||||
PWINDOW->m_iWorkspaceID = pWorkspace->m_iID;
|
PWINDOW->m_iWorkspaceID = pWorkspace->m_iID;
|
||||||
PWINDOW->m_iMonitorID = pWorkspace->m_iMonitorID;
|
PWINDOW->m_iMonitorID = pWorkspace->m_iMonitorID;
|
||||||
|
|
||||||
|
@ -312,7 +323,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||||
Debug::log(LOG, "Rule size, applying to {}", PWINDOW);
|
Debug::log(LOG, "Rule size, applying to {}", PWINDOW);
|
||||||
|
|
||||||
PWINDOW->m_vRealSize = Vector2D(SIZEX, SIZEY);
|
PWINDOW->m_vRealSize = Vector2D(SIZEX, SIZEY);
|
||||||
g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goalv());
|
g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goal());
|
||||||
|
|
||||||
PWINDOW->setHidden(false);
|
PWINDOW->setHidden(false);
|
||||||
} catch (...) { Debug::log(LOG, "Rule size failed, rule: {} -> {}", r.szRule, r.szValue); }
|
} catch (...) { Debug::log(LOG, "Rule size failed, rule: {} -> {}", r.szRule, r.szValue); }
|
||||||
|
@ -323,10 +334,10 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||||
const auto SIZEYSTR = VALUE.substr(VALUE.find(' ') + 1);
|
const auto SIZEYSTR = VALUE.substr(VALUE.find(' ') + 1);
|
||||||
|
|
||||||
const auto SIZE =
|
const auto SIZE =
|
||||||
Vector2D(std::max((double)std::stoll(SIZEXSTR), PWINDOW->m_vRealSize.goalv().x), std::max((double)std::stoll(SIZEYSTR), PWINDOW->m_vRealSize.goalv().y));
|
Vector2D(std::max((double)std::stoll(SIZEXSTR), PWINDOW->m_vRealSize.goal().x), std::max((double)std::stoll(SIZEYSTR), PWINDOW->m_vRealSize.goal().y));
|
||||||
|
|
||||||
PWINDOW->m_vRealSize = SIZE;
|
PWINDOW->m_vRealSize = SIZE;
|
||||||
g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goalv());
|
g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goal());
|
||||||
|
|
||||||
PWINDOW->setHidden(false);
|
PWINDOW->setHidden(false);
|
||||||
} catch (...) { Debug::log(LOG, "Rule minsize failed, rule: {} -> {}", r.szRule, r.szValue); }
|
} catch (...) { Debug::log(LOG, "Rule minsize failed, rule: {} -> {}", r.szRule, r.szValue); }
|
||||||
|
@ -337,10 +348,10 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||||
const auto SIZEYSTR = VALUE.substr(VALUE.find(' ') + 1);
|
const auto SIZEYSTR = VALUE.substr(VALUE.find(' ') + 1);
|
||||||
|
|
||||||
const auto SIZE =
|
const auto SIZE =
|
||||||
Vector2D(std::min((double)std::stoll(SIZEXSTR), PWINDOW->m_vRealSize.goalv().x), std::min((double)std::stoll(SIZEYSTR), PWINDOW->m_vRealSize.goalv().y));
|
Vector2D(std::min((double)std::stoll(SIZEXSTR), PWINDOW->m_vRealSize.goal().x), std::min((double)std::stoll(SIZEYSTR), PWINDOW->m_vRealSize.goal().y));
|
||||||
|
|
||||||
PWINDOW->m_vRealSize = SIZE;
|
PWINDOW->m_vRealSize = SIZE;
|
||||||
g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goalv());
|
g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goal());
|
||||||
|
|
||||||
PWINDOW->setHidden(false);
|
PWINDOW->setHidden(false);
|
||||||
} catch (...) { Debug::log(LOG, "Rule maxsize failed, rule: {} -> {}", r.szRule, r.szValue); }
|
} catch (...) { Debug::log(LOG, "Rule maxsize failed, rule: {} -> {}", r.szRule, r.szValue); }
|
||||||
|
@ -379,7 +390,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||||
posX = g_pInputManager->getMouseCoordsInternal().x - PMONITOR->vecPosition.x;
|
posX = g_pInputManager->getMouseCoordsInternal().x - PMONITOR->vecPosition.x;
|
||||||
} else {
|
} else {
|
||||||
posX = g_pInputManager->getMouseCoordsInternal().x - PMONITOR->vecPosition.x +
|
posX = g_pInputManager->getMouseCoordsInternal().x - PMONITOR->vecPosition.x +
|
||||||
(!POSXSTR.contains('%') ? std::stoi(POSXSTR) : std::stof(POSXSTR.substr(0, POSXSTR.length() - 1)) * 0.01 * PWINDOW->m_vRealSize.goalv().x);
|
(!POSXSTR.contains('%') ? std::stoi(POSXSTR) : std::stof(POSXSTR.substr(0, POSXSTR.length() - 1)) * 0.01 * PWINDOW->m_vRealSize.goal().x);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -398,7 +409,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||||
posY = g_pInputManager->getMouseCoordsInternal().y - PMONITOR->vecPosition.y;
|
posY = g_pInputManager->getMouseCoordsInternal().y - PMONITOR->vecPosition.y;
|
||||||
} else {
|
} else {
|
||||||
posY = g_pInputManager->getMouseCoordsInternal().y - PMONITOR->vecPosition.y +
|
posY = g_pInputManager->getMouseCoordsInternal().y - PMONITOR->vecPosition.y +
|
||||||
(!POSYSTR.contains('%') ? std::stoi(POSYSTR) : std::stof(POSYSTR.substr(0, POSYSTR.length() - 1)) * 0.01 * PWINDOW->m_vRealSize.goalv().y);
|
(!POSYSTR.contains('%') ? std::stoi(POSYSTR) : std::stof(POSYSTR.substr(0, POSYSTR.length() - 1)) * 0.01 * PWINDOW->m_vRealSize.goal().y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -406,10 +417,10 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||||
int borderSize = PWINDOW->getRealBorderSize();
|
int borderSize = PWINDOW->getRealBorderSize();
|
||||||
|
|
||||||
posX = std::clamp(posX, (int)(PMONITOR->vecReservedTopLeft.x + borderSize),
|
posX = std::clamp(posX, (int)(PMONITOR->vecReservedTopLeft.x + borderSize),
|
||||||
(int)(PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x - PWINDOW->m_vRealSize.goalv().x - borderSize));
|
(int)(PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x - PWINDOW->m_vRealSize.goal().x - borderSize));
|
||||||
|
|
||||||
posY = std::clamp(posY, (int)(PMONITOR->vecReservedTopLeft.y + borderSize),
|
posY = std::clamp(posY, (int)(PMONITOR->vecReservedTopLeft.y + borderSize),
|
||||||
(int)(PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y - PWINDOW->m_vRealSize.goalv().y - borderSize));
|
(int)(PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y - PWINDOW->m_vRealSize.goal().y - borderSize));
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug::log(LOG, "Rule move, applying to {}", PWINDOW);
|
Debug::log(LOG, "Rule move, applying to {}", PWINDOW);
|
||||||
|
@ -424,28 +435,28 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||||
if (ARGS[1] == "1")
|
if (ARGS[1] == "1")
|
||||||
RESERVEDOFFSET = (PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight) / 2.f;
|
RESERVEDOFFSET = (PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight) / 2.f;
|
||||||
|
|
||||||
PWINDOW->m_vRealPosition = PMONITOR->middle() - PWINDOW->m_vRealSize.goalv() / 2.f + RESERVEDOFFSET;
|
PWINDOW->m_vRealPosition = PMONITOR->middle() - PWINDOW->m_vRealSize.value() / 2.f + RESERVEDOFFSET;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// set the pseudo size to the GOAL of our current size
|
// set the pseudo size to the GOAL of our current size
|
||||||
// because the windows are animated on RealSize
|
// because the windows are animated on RealSize
|
||||||
PWINDOW->m_vPseudoSize = PWINDOW->m_vRealSize.goalv();
|
PWINDOW->m_vPseudoSize = PWINDOW->m_vRealSize.goal();
|
||||||
|
|
||||||
g_pCompositor->changeWindowZOrder(PWINDOW, true);
|
g_pCompositor->changeWindowZOrder(PWINDOW, true);
|
||||||
} else {
|
} else {
|
||||||
g_pLayoutManager->getCurrentLayout()->onWindowCreated(PWINDOW);
|
g_pLayoutManager->getCurrentLayout()->onWindowCreated(PWINDOW);
|
||||||
|
|
||||||
// Set the pseudo size here too so that it doesnt end up being 0x0
|
// Set the pseudo size here too so that it doesnt end up being 0x0
|
||||||
PWINDOW->m_vPseudoSize = PWINDOW->m_vRealSize.goalv() - Vector2D(10, 10);
|
PWINDOW->m_vPseudoSize = PWINDOW->m_vRealSize.goal() - Vector2D(10, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto PFOCUSEDWINDOWPREV = g_pCompositor->m_pLastWindow;
|
const auto PFOCUSEDWINDOWPREV = g_pCompositor->m_pLastWindow;
|
||||||
|
|
||||||
if (PWINDOW->m_sAdditionalConfigData.forceAllowsInput) {
|
if (PWINDOW->m_sAdditionalConfigData.forceAllowsInput) {
|
||||||
PWINDOW->m_bNoFocus = false;
|
PWINDOW->m_sAdditionalConfigData.noFocus = false;
|
||||||
PWINDOW->m_bNoInitialFocus = false;
|
PWINDOW->m_bNoInitialFocus = false;
|
||||||
PWINDOW->m_bX11ShouldntFocus = false;
|
PWINDOW->m_bX11ShouldntFocus = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check LS focus grab
|
// check LS focus grab
|
||||||
|
@ -454,9 +465,9 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||||
if (PLSFROMFOCUS && PLSFROMFOCUS->layerSurface->current.keyboard_interactive)
|
if (PLSFROMFOCUS && PLSFROMFOCUS->layerSurface->current.keyboard_interactive)
|
||||||
PWINDOW->m_bNoInitialFocus = true;
|
PWINDOW->m_bNoInitialFocus = true;
|
||||||
if (PWORKSPACE->m_bHasFullscreenWindow && !requestsFullscreen && !PWINDOW->m_bIsFloating) {
|
if (PWORKSPACE->m_bHasFullscreenWindow && !requestsFullscreen && !PWINDOW->m_bIsFloating) {
|
||||||
if (*PNEWTAKESOVERFS == 0)
|
if (**PNEWTAKESOVERFS == 0)
|
||||||
PWINDOW->m_bNoInitialFocus = true;
|
PWINDOW->m_bNoInitialFocus = true;
|
||||||
else if (*PNEWTAKESOVERFS == 2)
|
else if (**PNEWTAKESOVERFS == 2)
|
||||||
g_pCompositor->setWindowFullscreen(g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID), false, FULLSCREEN_INVALID);
|
g_pCompositor->setWindowFullscreen(g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID), false, FULLSCREEN_INVALID);
|
||||||
else if (PWORKSPACE->m_efFullscreenMode == FULLSCREEN_MAXIMIZED)
|
else if (PWORKSPACE->m_efFullscreenMode == FULLSCREEN_MAXIMIZED)
|
||||||
requestsMaximize = true;
|
requestsMaximize = true;
|
||||||
|
@ -464,22 +475,19 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||||
requestsFullscreen = true;
|
requestsFullscreen = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!PWINDOW->m_bNoFocus && !PWINDOW->m_bNoInitialFocus &&
|
if (!PWINDOW->m_sAdditionalConfigData.noFocus && !PWINDOW->m_bNoInitialFocus &&
|
||||||
(PWINDOW->m_iX11Type != 2 || (PWINDOW->m_bIsX11 && wlr_xwayland_or_surface_wants_focus(PWINDOW->m_uSurface.xwayland))) && !workspaceSilent &&
|
(PWINDOW->m_iX11Type != 2 || (PWINDOW->m_bIsX11 && wlr_xwayland_or_surface_wants_focus(PWINDOW->m_uSurface.xwayland))) && !workspaceSilent &&
|
||||||
(!PFORCEFOCUS || PFORCEFOCUS == PWINDOW)) {
|
(!PFORCEFOCUS || PFORCEFOCUS == PWINDOW)) {
|
||||||
g_pCompositor->focusWindow(PWINDOW);
|
g_pCompositor->focusWindow(PWINDOW);
|
||||||
PWINDOW->m_fActiveInactiveAlpha.setValueAndWarp(*PACTIVEALPHA);
|
PWINDOW->m_fActiveInactiveAlpha.setValueAndWarp(**PACTIVEALPHA);
|
||||||
PWINDOW->m_fDimPercent.setValueAndWarp(PWINDOW->m_sAdditionalConfigData.forceNoDim ? 0.f : *PDIMSTRENGTH);
|
PWINDOW->m_fDimPercent.setValueAndWarp(PWINDOW->m_sAdditionalConfigData.forceNoDim ? 0.f : **PDIMSTRENGTH);
|
||||||
} else {
|
} else {
|
||||||
PWINDOW->m_fActiveInactiveAlpha.setValueAndWarp(*PINACTIVEALPHA);
|
PWINDOW->m_fActiveInactiveAlpha.setValueAndWarp(**PINACTIVEALPHA);
|
||||||
PWINDOW->m_fDimPercent.setValueAndWarp(0);
|
PWINDOW->m_fDimPercent.setValueAndWarp(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug::log(LOG, "Window got assigned a surfaceTreeNode {:x}", (uintptr_t)PWINDOW->m_pSurfaceTree);
|
|
||||||
|
|
||||||
if (!PWINDOW->m_bIsX11) {
|
if (!PWINDOW->m_bIsX11) {
|
||||||
PWINDOW->hyprListener_setTitleWindow.initCallback(&PWINDOW->m_uSurface.xdg->toplevel->events.set_title, &Events::listener_setTitleWindow, PWINDOW, "XDG Window Late");
|
PWINDOW->hyprListener_setTitleWindow.initCallback(&PWINDOW->m_uSurface.xdg->toplevel->events.set_title, &Events::listener_setTitleWindow, PWINDOW, "XDG Window Late");
|
||||||
PWINDOW->hyprListener_newPopupXDG.initCallback(&PWINDOW->m_uSurface.xdg->events.new_popup, &Events::listener_newPopupXDG, PWINDOW, "XDG Window Late");
|
|
||||||
PWINDOW->hyprListener_requestMaximize.initCallback(&PWINDOW->m_uSurface.xdg->toplevel->events.request_maximize, &Events::listener_requestMaximize, PWINDOW,
|
PWINDOW->hyprListener_requestMaximize.initCallback(&PWINDOW->m_uSurface.xdg->toplevel->events.request_maximize, &Events::listener_requestMaximize, PWINDOW,
|
||||||
"XDG Window Late");
|
"XDG Window Late");
|
||||||
PWINDOW->hyprListener_requestMinimize.initCallback(&PWINDOW->m_uSurface.xdg->toplevel->events.request_minimize, &Events::listener_requestMinimize, PWINDOW,
|
PWINDOW->hyprListener_requestMinimize.initCallback(&PWINDOW->m_uSurface.xdg->toplevel->events.request_minimize, &Events::listener_requestMinimize, PWINDOW,
|
||||||
|
@ -504,8 +512,8 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||||
"XWayland Window Late");
|
"XWayland Window Late");
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((requestsFullscreen && (!PWINDOW->m_bNoFullscreenRequest || overridingNoFullscreen)) || (requestsMaximize && (!PWINDOW->m_bNoMaximizeRequest || overridingNoMaximize)) ||
|
if ((requestsFullscreen && (!(PWINDOW->m_eSuppressedEvents & SUPPRESS_FULLSCREEN) || overridingNoFullscreen)) ||
|
||||||
requestsFakeFullscreen) {
|
(requestsMaximize && (!(PWINDOW->m_eSuppressedEvents & SUPPRESS_MAXIMIZE) || overridingNoMaximize)) || requestsFakeFullscreen) {
|
||||||
// fix fullscreen on requested (basically do a switcheroo)
|
// fix fullscreen on requested (basically do a switcheroo)
|
||||||
if (PWORKSPACE->m_bHasFullscreenWindow) {
|
if (PWORKSPACE->m_bHasFullscreenWindow) {
|
||||||
const auto PFULLWINDOW = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID);
|
const auto PFULLWINDOW = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID);
|
||||||
|
@ -527,8 +535,6 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||||
// recheck idle inhibitors
|
// recheck idle inhibitors
|
||||||
g_pInputManager->recheckIdleInhibitorStatus();
|
g_pInputManager->recheckIdleInhibitorStatus();
|
||||||
|
|
||||||
PWINDOW->m_pSurfaceTree = SubsurfaceTree::createTreeRoot(PWINDOW->m_pWLSurface.wlr(), addViewCoords, PWINDOW, PWINDOW);
|
|
||||||
|
|
||||||
PWINDOW->updateToplevel();
|
PWINDOW->updateToplevel();
|
||||||
|
|
||||||
if (workspaceSilent) {
|
if (workspaceSilent) {
|
||||||
|
@ -540,7 +546,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// verify swallowing
|
// verify swallowing
|
||||||
if (*PSWALLOW && *PSWALLOWREGEX != STRVAL_EMPTY) {
|
if (**PSWALLOW && std::string{*PSWALLOWREGEX} != STRVAL_EMPTY) {
|
||||||
// don't swallow ourselves
|
// don't swallow ourselves
|
||||||
std::regex rgx(*PSWALLOWREGEX);
|
std::regex rgx(*PSWALLOWREGEX);
|
||||||
if (!std::regex_match(g_pXWaylandManager->getAppIDClass(PWINDOW), rgx)) {
|
if (!std::regex_match(g_pXWaylandManager->getAppIDClass(PWINDOW), rgx)) {
|
||||||
|
@ -587,7 +593,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||||
if (finalFound) {
|
if (finalFound) {
|
||||||
bool valid = std::regex_match(g_pXWaylandManager->getAppIDClass(finalFound), rgx);
|
bool valid = std::regex_match(g_pXWaylandManager->getAppIDClass(finalFound), rgx);
|
||||||
|
|
||||||
if (*PSWALLOWEXREGEX != STRVAL_EMPTY) {
|
if (std::string{*PSWALLOWEXREGEX} != STRVAL_EMPTY) {
|
||||||
std::regex exc(*PSWALLOWEXREGEX);
|
std::regex exc(*PSWALLOWEXREGEX);
|
||||||
|
|
||||||
valid = valid && !std::regex_match(g_pXWaylandManager->getTitle(finalFound), exc);
|
valid = valid && !std::regex_match(g_pXWaylandManager->getTitle(finalFound), exc);
|
||||||
|
@ -611,7 +617,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||||
|
|
||||||
PWINDOW->m_bFirstMap = false;
|
PWINDOW->m_bFirstMap = false;
|
||||||
|
|
||||||
Debug::log(LOG, "Map request dispatched, monitor {}, window pos: {:5j}, window size: {:5j}", PMONITOR->szName, PWINDOW->m_vRealPosition.goalv(), PWINDOW->m_vRealSize.goalv());
|
Debug::log(LOG, "Map request dispatched, monitor {}, window pos: {:5j}, window size: {:5j}", PMONITOR->szName, PWINDOW->m_vRealPosition.goal(), PWINDOW->m_vRealSize.goal());
|
||||||
|
|
||||||
auto workspaceID = requestedWorkspace != "" ? requestedWorkspace : PWORKSPACE->m_szName;
|
auto workspaceID = requestedWorkspace != "" ? requestedWorkspace : PWORKSPACE->m_szName;
|
||||||
g_pEventManager->postEvent(SHyprIPCEvent{"openwindow", std::format("{:x},{},{},{}", PWINDOW, workspaceID, g_pXWaylandManager->getAppIDClass(PWINDOW), PWINDOW->m_szTitle)});
|
g_pEventManager->postEvent(SHyprIPCEvent{"openwindow", std::format("{:x},{},{},{}", PWINDOW, workspaceID, g_pXWaylandManager->getAppIDClass(PWINDOW), PWINDOW->m_szTitle)});
|
||||||
|
@ -639,12 +645,16 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||||
g_pCompositor->setPreferredScaleForSurface(PWINDOW->m_pWLSurface.wlr(), PMONITOR->scale);
|
g_pCompositor->setPreferredScaleForSurface(PWINDOW->m_pWLSurface.wlr(), PMONITOR->scale);
|
||||||
g_pCompositor->setPreferredTransformForSurface(PWINDOW->m_pWLSurface.wlr(), PMONITOR->transform);
|
g_pCompositor->setPreferredTransformForSurface(PWINDOW->m_pWLSurface.wlr(), PMONITOR->transform);
|
||||||
|
|
||||||
g_pInputManager->sendMotionEventsToFocused();
|
if (!g_pCompositor->m_sSeat.mouse || !g_pCompositor->m_sSeat.mouse->constraintActive)
|
||||||
|
g_pInputManager->sendMotionEventsToFocused();
|
||||||
|
|
||||||
// fix some xwayland apps that don't behave nicely
|
// fix some xwayland apps that don't behave nicely
|
||||||
PWINDOW->m_vReportedSize = PWINDOW->m_vPendingReportedSize;
|
PWINDOW->m_vReportedSize = PWINDOW->m_vPendingReportedSize;
|
||||||
|
|
||||||
g_pCompositor->updateWorkspaceWindows(PWINDOW->m_iWorkspaceID);
|
g_pCompositor->updateWorkspaceWindows(PWINDOW->m_iWorkspaceID);
|
||||||
|
|
||||||
|
if (PMONITOR && PWINDOW->m_iX11Type == 2)
|
||||||
|
PWINDOW->m_fX11SurfaceScaledBy = PMONITOR->scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Events::listener_unmapWindow(void* owner, void* data) {
|
void Events::listener_unmapWindow(void* owner, void* data) {
|
||||||
|
@ -660,8 +670,8 @@ void Events::listener_unmapWindow(void* owner, void* data) {
|
||||||
|
|
||||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID);
|
const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID);
|
||||||
if (PMONITOR) {
|
if (PMONITOR) {
|
||||||
PWINDOW->m_vOriginalClosedPos = PWINDOW->m_vRealPosition.vec() - PMONITOR->vecPosition;
|
PWINDOW->m_vOriginalClosedPos = PWINDOW->m_vRealPosition.value() - PMONITOR->vecPosition;
|
||||||
PWINDOW->m_vOriginalClosedSize = PWINDOW->m_vRealSize.vec();
|
PWINDOW->m_vOriginalClosedSize = PWINDOW->m_vRealSize.value();
|
||||||
PWINDOW->m_eOriginalClosedExtents = PWINDOW->getFullWindowExtents();
|
PWINDOW->m_eOriginalClosedExtents = PWINDOW->getFullWindowExtents();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -673,7 +683,6 @@ void Events::listener_unmapWindow(void* owner, void* data) {
|
||||||
if (!PWINDOW->m_bIsX11) {
|
if (!PWINDOW->m_bIsX11) {
|
||||||
Debug::log(LOG, "Unregistered late callbacks XDG");
|
Debug::log(LOG, "Unregistered late callbacks XDG");
|
||||||
PWINDOW->hyprListener_setTitleWindow.removeCallback();
|
PWINDOW->hyprListener_setTitleWindow.removeCallback();
|
||||||
PWINDOW->hyprListener_newPopupXDG.removeCallback();
|
|
||||||
PWINDOW->hyprListener_requestMaximize.removeCallback();
|
PWINDOW->hyprListener_requestMaximize.removeCallback();
|
||||||
PWINDOW->hyprListener_requestMinimize.removeCallback();
|
PWINDOW->hyprListener_requestMinimize.removeCallback();
|
||||||
PWINDOW->hyprListener_requestMove.removeCallback();
|
PWINDOW->hyprListener_requestMove.removeCallback();
|
||||||
|
@ -745,19 +754,14 @@ void Events::listener_unmapWindow(void* owner, void* data) {
|
||||||
Debug::log(LOG, "Unmapped was not focused, ignoring a refocus.");
|
Debug::log(LOG, "Unmapped was not focused, ignoring a refocus.");
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug::log(LOG, "Destroying the SubSurface tree of unmapped window {}", PWINDOW);
|
|
||||||
SubsurfaceTree::destroySurfaceTree(PWINDOW->m_pSurfaceTree);
|
|
||||||
|
|
||||||
PWINDOW->m_pSurfaceTree = nullptr;
|
|
||||||
|
|
||||||
PWINDOW->m_bFadingOut = true;
|
PWINDOW->m_bFadingOut = true;
|
||||||
|
|
||||||
g_pCompositor->addToFadingOutSafe(PWINDOW);
|
g_pCompositor->addToFadingOutSafe(PWINDOW);
|
||||||
|
|
||||||
g_pHyprRenderer->damageMonitor(g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID));
|
g_pHyprRenderer->damageMonitor(g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID));
|
||||||
|
|
||||||
if (!PWINDOW->m_bX11DoesntWantBorders) // don't animate out if they weren't animated in.
|
if (!PWINDOW->m_bX11DoesntWantBorders) // don't animate out if they weren't animated in.
|
||||||
PWINDOW->m_vRealPosition = PWINDOW->m_vRealPosition.vec() + Vector2D(0.01f, 0.01f); // it has to be animated, otherwise onWindowPostCreateClose will ignore it
|
PWINDOW->m_vRealPosition = PWINDOW->m_vRealPosition.value() + Vector2D(0.01f, 0.01f); // it has to be animated, otherwise onWindowPostCreateClose will ignore it
|
||||||
|
|
||||||
// anims
|
// anims
|
||||||
g_pAnimationManager->onWindowPostCreateClose(PWINDOW, true);
|
g_pAnimationManager->onWindowPostCreateClose(PWINDOW, true);
|
||||||
|
@ -793,6 +797,30 @@ void Events::listener_ackConfigure(void* owner, void* data) {
|
||||||
void Events::listener_commitWindow(void* owner, void* data) {
|
void Events::listener_commitWindow(void* owner, void* data) {
|
||||||
CWindow* PWINDOW = (CWindow*)owner;
|
CWindow* PWINDOW = (CWindow*)owner;
|
||||||
|
|
||||||
|
if (!PWINDOW->m_bIsX11 && PWINDOW->m_uSurface.xdg->initial_commit) {
|
||||||
|
Vector2D predSize = g_pLayoutManager->getCurrentLayout()->predictSizeForNewWindow();
|
||||||
|
|
||||||
|
if (g_pXWaylandManager->shouldBeFloated(PWINDOW, true))
|
||||||
|
predSize = {};
|
||||||
|
|
||||||
|
Vector2D maxSize = Vector2D{PWINDOW->m_uSurface.xdg->toplevel->pending.max_width, PWINDOW->m_uSurface.xdg->toplevel->pending.max_height};
|
||||||
|
|
||||||
|
if ((maxSize.x > 0 && maxSize.x < predSize.x) || (maxSize.y > 0 && maxSize.y < predSize.y))
|
||||||
|
predSize = {};
|
||||||
|
|
||||||
|
for (auto& r : g_pConfigManager->getMatchingRules(PWINDOW)) {
|
||||||
|
if (r.szRule == "float") {
|
||||||
|
predSize = {};
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Debug::log(LOG, "Layout predicts size {} for {}", predSize, PWINDOW);
|
||||||
|
|
||||||
|
wlr_xdg_toplevel_set_size(PWINDOW->m_uSurface.xdg->toplevel, predSize.x, predSize.y);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!PWINDOW->m_bIsMapped || PWINDOW->isHidden())
|
if (!PWINDOW->m_bIsMapped || PWINDOW->isHidden())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -803,11 +831,14 @@ void Events::listener_commitWindow(void* owner, void* data) {
|
||||||
PWINDOW->m_pPendingSizeAck.reset();
|
PWINDOW->m_pPendingSizeAck.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
PWINDOW->updateSurfaceOutputs();
|
g_pHyprRenderer->damageSurface(PWINDOW->m_pWLSurface.wlr(), PWINDOW->m_vRealPosition.goal().x, PWINDOW->m_vRealPosition.goal().y,
|
||||||
|
|
||||||
g_pHyprRenderer->damageSurface(PWINDOW->m_pWLSurface.wlr(), PWINDOW->m_vRealPosition.goalv().x, PWINDOW->m_vRealPosition.goalv().y,
|
|
||||||
PWINDOW->m_bIsX11 ? 1.0 / PWINDOW->m_fX11SurfaceScaledBy : 1.0);
|
PWINDOW->m_bIsX11 ? 1.0 / PWINDOW->m_fX11SurfaceScaledBy : 1.0);
|
||||||
|
|
||||||
|
if (!PWINDOW->m_bIsX11) {
|
||||||
|
PWINDOW->m_pSubsurfaceHead->recheckDamageForSubsurfaces();
|
||||||
|
PWINDOW->m_pPopupHead->recheckTree();
|
||||||
|
}
|
||||||
|
|
||||||
if (PWINDOW->m_bIsX11 || !PWINDOW->m_bIsFloating || PWINDOW->m_bIsFullscreen)
|
if (PWINDOW->m_bIsX11 || !PWINDOW->m_bIsFloating || PWINDOW->m_bIsFullscreen)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -817,7 +848,7 @@ void Events::listener_commitWindow(void* owner, void* data) {
|
||||||
if (MAXSIZE < Vector2D{1, 1})
|
if (MAXSIZE < Vector2D{1, 1})
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const auto REALSIZE = PWINDOW->m_vRealSize.goalv();
|
const auto REALSIZE = PWINDOW->m_vRealSize.goal();
|
||||||
Vector2D newSize = REALSIZE;
|
Vector2D newSize = REALSIZE;
|
||||||
|
|
||||||
if (MAXSIZE.x < newSize.x)
|
if (MAXSIZE.x < newSize.x)
|
||||||
|
@ -831,7 +862,7 @@ void Events::listener_commitWindow(void* owner, void* data) {
|
||||||
|
|
||||||
const Vector2D DELTA = REALSIZE - newSize;
|
const Vector2D DELTA = REALSIZE - newSize;
|
||||||
|
|
||||||
PWINDOW->m_vRealPosition = PWINDOW->m_vRealPosition.goalv() + DELTA / 2.0;
|
PWINDOW->m_vRealPosition = PWINDOW->m_vRealPosition.goal() + DELTA / 2.0;
|
||||||
PWINDOW->m_vRealSize = newSize;
|
PWINDOW->m_vRealSize = newSize;
|
||||||
g_pXWaylandManager->setWindowSize(PWINDOW, newSize, true);
|
g_pXWaylandManager->setWindowSize(PWINDOW, newSize, true);
|
||||||
g_pHyprRenderer->damageWindow(PWINDOW);
|
g_pHyprRenderer->damageWindow(PWINDOW);
|
||||||
|
@ -861,14 +892,10 @@ void Events::listener_destroyWindow(void* owner, void* data) {
|
||||||
|
|
||||||
g_pLayoutManager->getCurrentLayout()->onWindowRemoved(PWINDOW);
|
g_pLayoutManager->getCurrentLayout()->onWindowRemoved(PWINDOW);
|
||||||
|
|
||||||
if (PWINDOW->m_pSurfaceTree) {
|
|
||||||
Debug::log(LOG, "Destroying Subsurface tree of {} in destroyWindow", PWINDOW);
|
|
||||||
SubsurfaceTree::destroySurfaceTree(PWINDOW->m_pSurfaceTree);
|
|
||||||
PWINDOW->m_pSurfaceTree = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
PWINDOW->m_bReadyToDelete = true;
|
PWINDOW->m_bReadyToDelete = true;
|
||||||
|
|
||||||
|
PWINDOW->m_uSurface.xdg = nullptr;
|
||||||
|
|
||||||
if (!PWINDOW->m_bFadingOut) {
|
if (!PWINDOW->m_bFadingOut) {
|
||||||
Debug::log(LOG, "Unmapped {} removed instantly", PWINDOW);
|
Debug::log(LOG, "Unmapped {} removed instantly", PWINDOW);
|
||||||
g_pCompositor->removeWindowFromVectorSafe(PWINDOW); // most likely X11 unmanaged or sumn
|
g_pCompositor->removeWindowFromVectorSafe(PWINDOW); // most likely X11 unmanaged or sumn
|
||||||
|
@ -906,7 +933,7 @@ void Events::listener_fullscreenWindow(void* owner, void* data) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PWINDOW->isHidden() || PWINDOW->m_bNoFullscreenRequest)
|
if (PWINDOW->isHidden() || (PWINDOW->m_eSuppressedEvents & SUPPRESS_FULLSCREEN))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
bool requestedFullState = false;
|
bool requestedFullState = false;
|
||||||
|
@ -960,7 +987,7 @@ void Events::listener_fullscreenWindow(void* owner, void* data) {
|
||||||
void Events::listener_activateXDG(wl_listener* listener, void* data) {
|
void Events::listener_activateXDG(wl_listener* listener, void* data) {
|
||||||
const auto E = (wlr_xdg_activation_v1_request_activate_event*)data;
|
const auto E = (wlr_xdg_activation_v1_request_activate_event*)data;
|
||||||
|
|
||||||
static auto* const PFOCUSONACTIVATE = &g_pConfigManager->getConfigValuePtr("misc:focus_on_activate")->intValue;
|
static auto* const PFOCUSONACTIVATE = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("misc:focus_on_activate");
|
||||||
|
|
||||||
Debug::log(LOG, "Activate request for surface at {:x}", (uintptr_t)E->surface);
|
Debug::log(LOG, "Activate request for surface at {:x}", (uintptr_t)E->surface);
|
||||||
|
|
||||||
|
@ -969,7 +996,7 @@ void Events::listener_activateXDG(wl_listener* listener, void* data) {
|
||||||
|
|
||||||
const auto PWINDOW = g_pCompositor->getWindowFromSurface(E->surface);
|
const auto PWINDOW = g_pCompositor->getWindowFromSurface(E->surface);
|
||||||
|
|
||||||
if (!PWINDOW || PWINDOW == g_pCompositor->m_pLastWindow)
|
if (!PWINDOW || PWINDOW == g_pCompositor->m_pLastWindow || (PWINDOW->m_eSuppressedEvents & SUPPRESS_ACTIVATE))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
g_pEventManager->postEvent(SHyprIPCEvent{"urgent", std::format("{:x}", (uintptr_t)PWINDOW)});
|
g_pEventManager->postEvent(SHyprIPCEvent{"urgent", std::format("{:x}", (uintptr_t)PWINDOW)});
|
||||||
|
@ -977,7 +1004,7 @@ void Events::listener_activateXDG(wl_listener* listener, void* data) {
|
||||||
|
|
||||||
PWINDOW->m_bIsUrgent = true;
|
PWINDOW->m_bIsUrgent = true;
|
||||||
|
|
||||||
if (!*PFOCUSONACTIVATE)
|
if (!**PFOCUSONACTIVATE || (PWINDOW->m_eSuppressedEvents & SUPPRESS_ACTIVATE_FOCUSONLY))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (PWINDOW->m_bIsFloating)
|
if (PWINDOW->m_bIsFloating)
|
||||||
|
@ -990,7 +1017,7 @@ void Events::listener_activateXDG(wl_listener* listener, void* data) {
|
||||||
void Events::listener_activateX11(void* owner, void* data) {
|
void Events::listener_activateX11(void* owner, void* data) {
|
||||||
const auto PWINDOW = (CWindow*)owner;
|
const auto PWINDOW = (CWindow*)owner;
|
||||||
|
|
||||||
static auto* const PFOCUSONACTIVATE = &g_pConfigManager->getConfigValuePtr("misc:focus_on_activate")->intValue;
|
static auto* const PFOCUSONACTIVATE = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("misc:focus_on_activate");
|
||||||
|
|
||||||
Debug::log(LOG, "X11 Activate request for window {}", PWINDOW);
|
Debug::log(LOG, "X11 Activate request for window {}", PWINDOW);
|
||||||
|
|
||||||
|
@ -1001,17 +1028,20 @@ void Events::listener_activateX11(void* owner, void* data) {
|
||||||
if (g_pCompositor->m_pLastWindow && g_pCompositor->m_pLastWindow->getPID() != PWINDOW->getPID())
|
if (g_pCompositor->m_pLastWindow && g_pCompositor->m_pLastWindow->getPID() != PWINDOW->getPID())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (!wlr_xwayland_or_surface_wants_focus(PWINDOW->m_uSurface.xwayland))
|
||||||
|
return;
|
||||||
|
|
||||||
g_pCompositor->focusWindow(PWINDOW);
|
g_pCompositor->focusWindow(PWINDOW);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PWINDOW == g_pCompositor->m_pLastWindow)
|
if (PWINDOW == g_pCompositor->m_pLastWindow || (PWINDOW->m_eSuppressedEvents & SUPPRESS_ACTIVATE))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
g_pEventManager->postEvent(SHyprIPCEvent{"urgent", std::format("{:x}", (uintptr_t)PWINDOW)});
|
g_pEventManager->postEvent(SHyprIPCEvent{"urgent", std::format("{:x}", (uintptr_t)PWINDOW)});
|
||||||
EMIT_HOOK_EVENT("urgent", PWINDOW);
|
EMIT_HOOK_EVENT("urgent", PWINDOW);
|
||||||
|
|
||||||
if (!*PFOCUSONACTIVATE)
|
if (!**PFOCUSONACTIVATE || (PWINDOW->m_eSuppressedEvents & SUPPRESS_ACTIVATE_FOCUSONLY))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (PWINDOW->m_bIsFloating)
|
if (PWINDOW->m_bIsFloating)
|
||||||
|
@ -1030,13 +1060,15 @@ void Events::listener_configureX11(void* owner, void* data) {
|
||||||
wlr_xwayland_surface_configure(PWINDOW->m_uSurface.xwayland, E->x, E->y, E->width, E->height);
|
wlr_xwayland_surface_configure(PWINDOW->m_uSurface.xwayland, E->x, E->y, E->width, E->height);
|
||||||
PWINDOW->m_vPendingReportedSize = {E->width, E->height};
|
PWINDOW->m_vPendingReportedSize = {E->width, E->height};
|
||||||
PWINDOW->m_vReportedSize = {E->width, E->height};
|
PWINDOW->m_vReportedSize = {E->width, E->height};
|
||||||
|
if (const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID); PMONITOR)
|
||||||
|
PWINDOW->m_fX11SurfaceScaledBy = PMONITOR->scale;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_pHyprRenderer->damageWindow(PWINDOW);
|
g_pHyprRenderer->damageWindow(PWINDOW);
|
||||||
|
|
||||||
if (!PWINDOW->m_bIsFloating || PWINDOW->m_bIsFullscreen || g_pInputManager->currentlyDraggedWindow == PWINDOW) {
|
if (!PWINDOW->m_bIsFloating || PWINDOW->m_bIsFullscreen || g_pInputManager->currentlyDraggedWindow == PWINDOW) {
|
||||||
g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goalv(), true);
|
g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goal(), true);
|
||||||
g_pInputManager->refocus();
|
g_pInputManager->refocus();
|
||||||
g_pHyprRenderer->damageWindow(PWINDOW);
|
g_pHyprRenderer->damageWindow(PWINDOW);
|
||||||
return;
|
return;
|
||||||
|
@ -1052,17 +1084,16 @@ void Events::listener_configureX11(void* owner, void* data) {
|
||||||
PWINDOW->m_vRealPosition.setValueAndWarp(LOGICALPOS);
|
PWINDOW->m_vRealPosition.setValueAndWarp(LOGICALPOS);
|
||||||
PWINDOW->m_vRealSize.setValueAndWarp(Vector2D(E->width, E->height));
|
PWINDOW->m_vRealSize.setValueAndWarp(Vector2D(E->width, E->height));
|
||||||
|
|
||||||
static auto* const PXWLFORCESCALEZERO = &g_pConfigManager->getConfigValuePtr("xwayland:force_zero_scaling")->intValue;
|
static auto* const PXWLFORCESCALEZERO = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("xwayland:force_zero_scaling");
|
||||||
if (*PXWLFORCESCALEZERO) {
|
if (**PXWLFORCESCALEZERO) {
|
||||||
if (const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID); PMONITOR) {
|
if (const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID); PMONITOR) {
|
||||||
const Vector2D DELTA = PWINDOW->m_vRealSize.goalv() - PWINDOW->m_vRealSize.goalv() / PMONITOR->scale;
|
PWINDOW->m_vRealSize.setValueAndWarp(PWINDOW->m_vRealSize.goal() / PMONITOR->scale);
|
||||||
PWINDOW->m_vRealSize.setValueAndWarp(PWINDOW->m_vRealSize.goalv() / PMONITOR->scale);
|
PWINDOW->m_fX11SurfaceScaledBy = PMONITOR->scale;
|
||||||
PWINDOW->m_vRealPosition.setValueAndWarp(PWINDOW->m_vRealPosition.goalv() + DELTA / 2.0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PWINDOW->m_vPosition = PWINDOW->m_vRealPosition.vec();
|
PWINDOW->m_vPosition = PWINDOW->m_vRealPosition.value();
|
||||||
PWINDOW->m_vSize = PWINDOW->m_vRealSize.vec();
|
PWINDOW->m_vSize = PWINDOW->m_vRealSize.value();
|
||||||
|
|
||||||
wlr_xwayland_surface_configure(PWINDOW->m_uSurface.xwayland, E->x, E->y, E->width, E->height);
|
wlr_xwayland_surface_configure(PWINDOW->m_uSurface.xwayland, E->x, E->y, E->width, E->height);
|
||||||
|
|
||||||
|
@ -1074,7 +1105,7 @@ void Events::listener_configureX11(void* owner, void* data) {
|
||||||
if (!g_pCompositor->isWorkspaceVisible(PWINDOW->m_iWorkspaceID))
|
if (!g_pCompositor->isWorkspaceVisible(PWINDOW->m_iWorkspaceID))
|
||||||
return; // further things are only for visible windows
|
return; // further things are only for visible windows
|
||||||
|
|
||||||
PWINDOW->m_iWorkspaceID = g_pCompositor->getMonitorFromVector(PWINDOW->m_vRealPosition.vec() + PWINDOW->m_vRealSize.vec() / 2.f)->activeWorkspace;
|
PWINDOW->m_iWorkspaceID = g_pCompositor->getMonitorFromVector(PWINDOW->m_vRealPosition.value() + PWINDOW->m_vRealSize.value() / 2.f)->activeWorkspace;
|
||||||
|
|
||||||
g_pCompositor->changeWindowZOrder(PWINDOW, true);
|
g_pCompositor->changeWindowZOrder(PWINDOW, true);
|
||||||
|
|
||||||
|
@ -1092,8 +1123,8 @@ void Events::listener_unmanagedSetGeometry(void* owner, void* data) {
|
||||||
if (!PWINDOW->m_bIsMapped)
|
if (!PWINDOW->m_bIsMapped)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const auto POS = PWINDOW->m_vRealPosition.goalv();
|
const auto POS = PWINDOW->m_vRealPosition.goal();
|
||||||
const auto SIZ = PWINDOW->m_vRealSize.goalv();
|
const auto SIZ = PWINDOW->m_vRealSize.goal();
|
||||||
|
|
||||||
if (PWINDOW->m_uSurface.xwayland->width > 1 && PWINDOW->m_uSurface.xwayland->height > 1)
|
if (PWINDOW->m_uSurface.xwayland->width > 1 && PWINDOW->m_uSurface.xwayland->height > 1)
|
||||||
PWINDOW->setHidden(false);
|
PWINDOW->setHidden(false);
|
||||||
|
@ -1101,12 +1132,12 @@ void Events::listener_unmanagedSetGeometry(void* owner, void* data) {
|
||||||
PWINDOW->setHidden(true);
|
PWINDOW->setHidden(true);
|
||||||
|
|
||||||
if (PWINDOW->m_bIsFullscreen || !PWINDOW->m_bIsFloating) {
|
if (PWINDOW->m_bIsFullscreen || !PWINDOW->m_bIsFloating) {
|
||||||
g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goalv(), true);
|
g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goal(), true);
|
||||||
g_pHyprRenderer->damageWindow(PWINDOW);
|
g_pHyprRenderer->damageWindow(PWINDOW);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
static auto* const PXWLFORCESCALEZERO = &g_pConfigManager->getConfigValuePtr("xwayland:force_zero_scaling")->intValue;
|
static auto* const PXWLFORCESCALEZERO = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("xwayland:force_zero_scaling");
|
||||||
|
|
||||||
const auto LOGICALPOS = g_pXWaylandManager->xwaylandToWaylandCoords({PWINDOW->m_uSurface.xwayland->x, PWINDOW->m_uSurface.xwayland->y});
|
const auto LOGICALPOS = g_pXWaylandManager->xwaylandToWaylandCoords({PWINDOW->m_uSurface.xwayland->x, PWINDOW->m_uSurface.xwayland->y});
|
||||||
|
|
||||||
|
@ -1121,26 +1152,25 @@ void Events::listener_unmanagedSetGeometry(void* owner, void* data) {
|
||||||
if (abs(std::floor(SIZ.x) - PWINDOW->m_uSurface.xwayland->width) > 2 || abs(std::floor(SIZ.y) - PWINDOW->m_uSurface.xwayland->height) > 2)
|
if (abs(std::floor(SIZ.x) - PWINDOW->m_uSurface.xwayland->width) > 2 || abs(std::floor(SIZ.y) - PWINDOW->m_uSurface.xwayland->height) > 2)
|
||||||
PWINDOW->m_vRealSize.setValueAndWarp(Vector2D(PWINDOW->m_uSurface.xwayland->width, PWINDOW->m_uSurface.xwayland->height));
|
PWINDOW->m_vRealSize.setValueAndWarp(Vector2D(PWINDOW->m_uSurface.xwayland->width, PWINDOW->m_uSurface.xwayland->height));
|
||||||
|
|
||||||
if (*PXWLFORCESCALEZERO) {
|
if (**PXWLFORCESCALEZERO) {
|
||||||
if (const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID); PMONITOR) {
|
if (const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID); PMONITOR) {
|
||||||
const Vector2D DELTA = PWINDOW->m_vRealSize.goalv() - PWINDOW->m_vRealSize.goalv() / PMONITOR->scale;
|
const Vector2D DELTA = PWINDOW->m_vRealSize.goal() - PWINDOW->m_vRealSize.goal() / PMONITOR->scale;
|
||||||
PWINDOW->m_vRealSize.setValueAndWarp(PWINDOW->m_vRealSize.goalv() / PMONITOR->scale);
|
PWINDOW->m_vRealSize.setValueAndWarp(PWINDOW->m_vRealSize.goal() / PMONITOR->scale);
|
||||||
PWINDOW->m_vRealPosition.setValueAndWarp(PWINDOW->m_vRealPosition.goalv() + DELTA / 2.0);
|
PWINDOW->m_vRealPosition.setValueAndWarp(PWINDOW->m_vRealPosition.goal() + DELTA / 2.0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PWINDOW->m_vPosition = PWINDOW->m_vRealPosition.goalv();
|
PWINDOW->m_vPosition = PWINDOW->m_vRealPosition.goal();
|
||||||
PWINDOW->m_vSize = PWINDOW->m_vRealSize.goalv();
|
PWINDOW->m_vSize = PWINDOW->m_vRealSize.goal();
|
||||||
|
|
||||||
PWINDOW->m_iWorkspaceID = g_pCompositor->getMonitorFromVector(PWINDOW->m_vRealPosition.vec() + PWINDOW->m_vRealSize.vec() / 2.f)->activeWorkspace;
|
PWINDOW->m_iWorkspaceID = g_pCompositor->getMonitorFromVector(PWINDOW->m_vRealPosition.value() + PWINDOW->m_vRealSize.value() / 2.f)->activeWorkspace;
|
||||||
|
|
||||||
g_pCompositor->changeWindowZOrder(PWINDOW, true);
|
g_pCompositor->changeWindowZOrder(PWINDOW, true);
|
||||||
PWINDOW->updateWindowDecos();
|
PWINDOW->updateWindowDecos();
|
||||||
g_pHyprRenderer->damageWindow(PWINDOW);
|
g_pHyprRenderer->damageWindow(PWINDOW);
|
||||||
|
|
||||||
PWINDOW->m_vReportedPosition = PWINDOW->m_vRealPosition.goalv();
|
PWINDOW->m_vReportedPosition = PWINDOW->m_vRealPosition.goal();
|
||||||
PWINDOW->m_vReportedSize = PWINDOW->m_vRealSize.goalv();
|
PWINDOW->m_vPendingReportedSize = PWINDOW->m_vRealSize.goal();
|
||||||
PWINDOW->m_vPendingReportedSize = PWINDOW->m_vReportedSize;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1211,7 +1241,7 @@ void Events::listener_NewXDGDeco(wl_listener* listener, void* data) {
|
||||||
void Events::listener_requestMaximize(void* owner, void* data) {
|
void Events::listener_requestMaximize(void* owner, void* data) {
|
||||||
const auto PWINDOW = (CWindow*)owner;
|
const auto PWINDOW = (CWindow*)owner;
|
||||||
|
|
||||||
if (PWINDOW->m_bNoMaximizeRequest)
|
if (PWINDOW->m_eSuppressedEvents & SUPPRESS_MAXIMIZE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Debug::log(LOG, "Maximize request for {}", PWINDOW);
|
Debug::log(LOG, "Maximize request for {}", PWINDOW);
|
||||||
|
|
|
@ -2,12 +2,11 @@
|
||||||
#include "../managers/AnimationManager.hpp"
|
#include "../managers/AnimationManager.hpp"
|
||||||
#include "../config/ConfigManager.hpp"
|
#include "../config/ConfigManager.hpp"
|
||||||
|
|
||||||
CAnimatedVariable::CAnimatedVariable() {
|
CBaseAnimatedVariable::CBaseAnimatedVariable(ANIMATEDVARTYPE type) : m_Type(type) {
|
||||||
; // dummy var
|
; // dummy var
|
||||||
}
|
}
|
||||||
|
|
||||||
void CAnimatedVariable::create(ANIMATEDVARTYPE type, SAnimationPropertyConfig* pAnimConfig, void* pWindow, AVARDAMAGEPOLICY policy) {
|
void CBaseAnimatedVariable::create(SAnimationPropertyConfig* pAnimConfig, void* pWindow, AVARDAMAGEPOLICY policy) {
|
||||||
m_eVarType = type;
|
|
||||||
m_eDamagePolicy = policy;
|
m_eDamagePolicy = policy;
|
||||||
m_pConfig = pAnimConfig;
|
m_pConfig = pAnimConfig;
|
||||||
m_pWindow = pWindow;
|
m_pWindow = pWindow;
|
||||||
|
@ -15,42 +14,11 @@ void CAnimatedVariable::create(ANIMATEDVARTYPE type, SAnimationPropertyConfig* p
|
||||||
m_bDummy = false;
|
m_bDummy = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CAnimatedVariable::create(ANIMATEDVARTYPE type, std::any val, SAnimationPropertyConfig* pAnimConfig, void* pWindow, AVARDAMAGEPOLICY policy) {
|
CBaseAnimatedVariable::~CBaseAnimatedVariable() {
|
||||||
create(type, pAnimConfig, pWindow, policy);
|
|
||||||
|
|
||||||
try {
|
|
||||||
switch (type) {
|
|
||||||
case AVARTYPE_FLOAT: {
|
|
||||||
const auto V = std::any_cast<float>(val);
|
|
||||||
m_fValue = V;
|
|
||||||
m_fGoal = V;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case AVARTYPE_VECTOR: {
|
|
||||||
const auto V = std::any_cast<Vector2D>(val);
|
|
||||||
m_vValue = V;
|
|
||||||
m_vGoal = V;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case AVARTYPE_COLOR: {
|
|
||||||
const auto V = std::any_cast<CColor>(val);
|
|
||||||
m_cValue = V;
|
|
||||||
m_cGoal = V;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: ASSERT(false); break;
|
|
||||||
}
|
|
||||||
} catch (std::exception& e) {
|
|
||||||
Debug::log(ERR, "CAnimatedVariable create error: {}", e.what());
|
|
||||||
RASSERT(false, "CAnimatedVariable create error: {}", e.what());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CAnimatedVariable::~CAnimatedVariable() {
|
|
||||||
unregister();
|
unregister();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CAnimatedVariable::unregister() {
|
void CBaseAnimatedVariable::unregister() {
|
||||||
if (!g_pAnimationManager)
|
if (!g_pAnimationManager)
|
||||||
return;
|
return;
|
||||||
std::erase_if(g_pAnimationManager->m_vAnimatedVariables, [&](const auto& other) { return other == this; });
|
std::erase_if(g_pAnimationManager->m_vAnimatedVariables, [&](const auto& other) { return other == this; });
|
||||||
|
@ -58,23 +26,26 @@ void CAnimatedVariable::unregister() {
|
||||||
disconnectFromActive();
|
disconnectFromActive();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CAnimatedVariable::registerVar() {
|
void CBaseAnimatedVariable::registerVar() {
|
||||||
if (!m_bIsRegistered)
|
if (!m_bIsRegistered)
|
||||||
g_pAnimationManager->m_vAnimatedVariables.push_back(this);
|
g_pAnimationManager->m_vAnimatedVariables.push_back(this);
|
||||||
m_bIsRegistered = true;
|
m_bIsRegistered = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int CAnimatedVariable::getDurationLeftMs() {
|
int CBaseAnimatedVariable::getDurationLeftMs() {
|
||||||
return std::max(
|
return std::max(
|
||||||
(int)(m_pConfig->pValues->internalSpeed * 100) - (int)std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now() - animationBegin).count(), 0);
|
(int)(m_pConfig->pValues->internalSpeed * 100) - (int)std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now() - animationBegin).count(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
float CAnimatedVariable::getPercent() {
|
float CBaseAnimatedVariable::getPercent() {
|
||||||
const auto DURATIONPASSED = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now() - animationBegin).count();
|
const auto DURATIONPASSED = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now() - animationBegin).count();
|
||||||
return std::clamp((DURATIONPASSED / 100.f) / m_pConfig->pValues->internalSpeed, 0.f, 1.f);
|
return std::clamp((DURATIONPASSED / 100.f) / m_pConfig->pValues->internalSpeed, 0.f, 1.f);
|
||||||
}
|
}
|
||||||
|
|
||||||
float CAnimatedVariable::getCurveValue() {
|
float CBaseAnimatedVariable::getCurveValue() {
|
||||||
|
if (!m_bIsBeingAnimated)
|
||||||
|
return 1.f;
|
||||||
|
|
||||||
const auto SPENT = getPercent();
|
const auto SPENT = getPercent();
|
||||||
|
|
||||||
if (SPENT >= 1.f)
|
if (SPENT >= 1.f)
|
||||||
|
@ -83,7 +54,7 @@ float CAnimatedVariable::getCurveValue() {
|
||||||
return g_pAnimationManager->getBezier(m_pConfig->pValues->internalBezier)->getYForPoint(SPENT);
|
return g_pAnimationManager->getBezier(m_pConfig->pValues->internalBezier)->getYForPoint(SPENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CAnimatedVariable::connectToActive() {
|
void CBaseAnimatedVariable::connectToActive() {
|
||||||
g_pAnimationManager->scheduleTick(); // otherwise the animation manager will never pick this up
|
g_pAnimationManager->scheduleTick(); // otherwise the animation manager will never pick this up
|
||||||
|
|
||||||
if (!m_bIsConnectedToActive)
|
if (!m_bIsConnectedToActive)
|
||||||
|
@ -92,7 +63,7 @@ void CAnimatedVariable::connectToActive() {
|
||||||
m_bIsConnectedToActive = true;
|
m_bIsConnectedToActive = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CAnimatedVariable::disconnectFromActive() {
|
void CBaseAnimatedVariable::disconnectFromActive() {
|
||||||
std::erase_if(g_pAnimationManager->m_vActiveAnimatedVariables, [&](const auto& other) { return other == this; });
|
std::erase_if(g_pAnimationManager->m_vActiveAnimatedVariables, [&](const auto& other) { return other == this; });
|
||||||
m_bIsConnectedToActive = false;
|
m_bIsConnectedToActive = false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <any>
|
#include <any>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
#include <type_traits>
|
||||||
#include "Vector2D.hpp"
|
#include "Vector2D.hpp"
|
||||||
#include "Color.hpp"
|
#include "Color.hpp"
|
||||||
#include "../macros.hpp"
|
#include "../macros.hpp"
|
||||||
|
@ -15,6 +16,30 @@ enum ANIMATEDVARTYPE {
|
||||||
AVARTYPE_COLOR
|
AVARTYPE_COLOR
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Utility to bind a type with its corresponding ANIMATEDVARTYPE
|
||||||
|
template <class T>
|
||||||
|
struct typeToANIMATEDVARTYPE_t {
|
||||||
|
static constexpr ANIMATEDVARTYPE value = AVARTYPE_INVALID;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct typeToANIMATEDVARTYPE_t<float> {
|
||||||
|
static constexpr ANIMATEDVARTYPE value = AVARTYPE_FLOAT;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct typeToANIMATEDVARTYPE_t<Vector2D> {
|
||||||
|
static constexpr ANIMATEDVARTYPE value = AVARTYPE_VECTOR;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct typeToANIMATEDVARTYPE_t<CColor> {
|
||||||
|
static constexpr ANIMATEDVARTYPE value = AVARTYPE_COLOR;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
inline constexpr ANIMATEDVARTYPE typeToANIMATEDVARTYPE = typeToANIMATEDVARTYPE_t<T>::value;
|
||||||
|
|
||||||
enum AVARDAMAGEPOLICY {
|
enum AVARDAMAGEPOLICY {
|
||||||
AVARDAMAGE_NONE = -1,
|
AVARDAMAGE_NONE = -1,
|
||||||
AVARDAMAGE_ENTIRE = 0,
|
AVARDAMAGE_ENTIRE = 0,
|
||||||
|
@ -28,174 +53,34 @@ struct SLayerSurface;
|
||||||
struct SAnimationPropertyConfig;
|
struct SAnimationPropertyConfig;
|
||||||
class CHyprRenderer;
|
class CHyprRenderer;
|
||||||
|
|
||||||
class CAnimatedVariable {
|
// Utility to define a concept as a list of possible type
|
||||||
|
template <class T, class... U>
|
||||||
|
concept OneOf = (... or std::same_as<T, U>);
|
||||||
|
|
||||||
|
// Concept to describe which type can be placed into CAnimatedVariable
|
||||||
|
// This is mainly to get better errors if we put a type that's not supported
|
||||||
|
// Otherwise template errors are ugly
|
||||||
|
template <class T>
|
||||||
|
concept Animable = OneOf<T, Vector2D, float, CColor>;
|
||||||
|
|
||||||
|
class CBaseAnimatedVariable {
|
||||||
public:
|
public:
|
||||||
CAnimatedVariable(); // dummy var
|
CBaseAnimatedVariable(ANIMATEDVARTYPE type);
|
||||||
|
void create(SAnimationPropertyConfig* pAnimConfig, void* pWindow, AVARDAMAGEPOLICY policy);
|
||||||
|
|
||||||
void create(ANIMATEDVARTYPE, SAnimationPropertyConfig*, void* pWindow, AVARDAMAGEPOLICY);
|
CBaseAnimatedVariable(const CBaseAnimatedVariable&) = delete;
|
||||||
void create(ANIMATEDVARTYPE, std::any val, SAnimationPropertyConfig*, void* pWindow, AVARDAMAGEPOLICY);
|
CBaseAnimatedVariable(CBaseAnimatedVariable&&) = delete;
|
||||||
|
CBaseAnimatedVariable& operator=(const CBaseAnimatedVariable&) = delete;
|
||||||
|
CBaseAnimatedVariable& operator=(CBaseAnimatedVariable&&) = delete;
|
||||||
|
|
||||||
CAnimatedVariable(const CAnimatedVariable&) = delete;
|
virtual ~CBaseAnimatedVariable();
|
||||||
CAnimatedVariable(CAnimatedVariable&&) = delete;
|
|
||||||
CAnimatedVariable& operator=(const CAnimatedVariable&) = delete;
|
|
||||||
CAnimatedVariable& operator=(CAnimatedVariable&&) = delete;
|
|
||||||
|
|
||||||
~CAnimatedVariable();
|
void unregister();
|
||||||
|
void registerVar();
|
||||||
|
|
||||||
void unregister();
|
virtual void warp(bool endCallback = true) = 0;
|
||||||
void registerVar();
|
|
||||||
|
|
||||||
// gets the current vector value (real time)
|
|
||||||
const Vector2D& vec() const {
|
|
||||||
return m_vValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// gets the current float value (real time)
|
|
||||||
const float& fl() const {
|
|
||||||
return m_fValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// gets the current color value (real time)
|
|
||||||
const CColor& col() const {
|
|
||||||
return m_cValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// gets the goal vector value
|
|
||||||
const Vector2D& goalv() const {
|
|
||||||
return m_vGoal;
|
|
||||||
}
|
|
||||||
|
|
||||||
// gets the goal float value
|
|
||||||
const float& goalf() const {
|
|
||||||
return m_fGoal;
|
|
||||||
}
|
|
||||||
|
|
||||||
// gets the goal color value
|
|
||||||
const CColor& goalc() const {
|
|
||||||
return m_cGoal;
|
|
||||||
}
|
|
||||||
|
|
||||||
CAnimatedVariable& operator=(const Vector2D& v) {
|
|
||||||
if (v == m_vGoal)
|
|
||||||
return *this;
|
|
||||||
|
|
||||||
m_vGoal = v;
|
|
||||||
animationBegin = std::chrono::system_clock::now();
|
|
||||||
m_vBegun = m_vValue;
|
|
||||||
|
|
||||||
onAnimationBegin();
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
CAnimatedVariable& operator=(const float& v) {
|
|
||||||
if (v == m_fGoal)
|
|
||||||
return *this;
|
|
||||||
|
|
||||||
m_fGoal = v;
|
|
||||||
animationBegin = std::chrono::system_clock::now();
|
|
||||||
m_fBegun = m_fValue;
|
|
||||||
|
|
||||||
onAnimationBegin();
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
CAnimatedVariable& operator=(const CColor& v) {
|
|
||||||
if (v == m_cGoal)
|
|
||||||
return *this;
|
|
||||||
|
|
||||||
m_cGoal = v;
|
|
||||||
animationBegin = std::chrono::system_clock::now();
|
|
||||||
m_cBegun = m_cValue;
|
|
||||||
|
|
||||||
onAnimationBegin();
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sets the actual stored value, without affecting the goal, but resets the timer
|
|
||||||
void setValue(const Vector2D& v) {
|
|
||||||
if (v == m_vValue)
|
|
||||||
return;
|
|
||||||
|
|
||||||
m_vValue = v;
|
|
||||||
animationBegin = std::chrono::system_clock::now();
|
|
||||||
m_vBegun = m_vValue;
|
|
||||||
|
|
||||||
onAnimationBegin();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sets the actual stored value, without affecting the goal, but resets the timer
|
|
||||||
void setValue(const float& v) {
|
|
||||||
if (v == m_fValue)
|
|
||||||
return;
|
|
||||||
|
|
||||||
m_fValue = v;
|
|
||||||
animationBegin = std::chrono::system_clock::now();
|
|
||||||
m_vBegun = m_vValue;
|
|
||||||
|
|
||||||
onAnimationBegin();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sets the actual stored value, without affecting the goal, but resets the timer
|
|
||||||
void setValue(const CColor& v) {
|
|
||||||
if (v == m_cValue)
|
|
||||||
return;
|
|
||||||
|
|
||||||
m_cValue = v;
|
|
||||||
animationBegin = std::chrono::system_clock::now();
|
|
||||||
m_vBegun = m_vValue;
|
|
||||||
|
|
||||||
onAnimationBegin();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sets the actual value and goal
|
|
||||||
void setValueAndWarp(const Vector2D& v) {
|
|
||||||
m_vGoal = v;
|
|
||||||
warp();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sets the actual value and goal
|
|
||||||
void setValueAndWarp(const float& v) {
|
|
||||||
m_fGoal = v;
|
|
||||||
warp();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sets the actual value and goal
|
|
||||||
void setValueAndWarp(const CColor& v) {
|
|
||||||
m_cGoal = v;
|
|
||||||
warp();
|
|
||||||
}
|
|
||||||
|
|
||||||
// checks if an animation is in progress
|
|
||||||
inline bool isBeingAnimated() {
|
|
||||||
return m_bIsBeingAnimated;
|
|
||||||
}
|
|
||||||
|
|
||||||
void warp(bool endCallback = true) {
|
|
||||||
switch (m_eVarType) {
|
|
||||||
case AVARTYPE_FLOAT: {
|
|
||||||
m_fValue = m_fGoal;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case AVARTYPE_VECTOR: {
|
|
||||||
m_vValue = m_vGoal;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case AVARTYPE_COLOR: {
|
|
||||||
m_cValue = m_cGoal;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: UNREACHABLE();
|
|
||||||
}
|
|
||||||
|
|
||||||
m_bIsBeingAnimated = false;
|
|
||||||
|
|
||||||
if (endCallback)
|
|
||||||
onAnimationEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
//
|
||||||
void setConfig(SAnimationPropertyConfig* pConfig) {
|
void setConfig(SAnimationPropertyConfig* pConfig) {
|
||||||
m_pConfig = pConfig;
|
m_pConfig = pConfig;
|
||||||
}
|
}
|
||||||
|
@ -212,6 +97,11 @@ class CAnimatedVariable {
|
||||||
/* returns the current curve value */
|
/* returns the current curve value */
|
||||||
float getCurveValue();
|
float getCurveValue();
|
||||||
|
|
||||||
|
// checks if an animation is in progress
|
||||||
|
inline bool isBeingAnimated() {
|
||||||
|
return m_bIsBeingAnimated;
|
||||||
|
}
|
||||||
|
|
||||||
/* sets a function to be ran when the animation finishes.
|
/* sets a function to be ran when the animation finishes.
|
||||||
if an animation is not running, runs instantly.
|
if an animation is not running, runs instantly.
|
||||||
if "remove" is set to true, will remove the callback when ran. */
|
if "remove" is set to true, will remove the callback when ran. */
|
||||||
|
@ -245,20 +135,7 @@ class CAnimatedVariable {
|
||||||
m_bRemoveEndAfterRan = false;
|
m_bRemoveEndAfterRan = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
Vector2D m_vValue = Vector2D(0, 0);
|
|
||||||
float m_fValue = 0;
|
|
||||||
CColor m_cValue;
|
|
||||||
|
|
||||||
Vector2D m_vGoal = Vector2D(0, 0);
|
|
||||||
float m_fGoal = 0;
|
|
||||||
CColor m_cGoal;
|
|
||||||
|
|
||||||
Vector2D m_vBegun = Vector2D(0, 0);
|
|
||||||
float m_fBegun = 0;
|
|
||||||
CColor m_cBegun;
|
|
||||||
|
|
||||||
// owners
|
|
||||||
void* m_pWindow = nullptr;
|
void* m_pWindow = nullptr;
|
||||||
void* m_pWorkspace = nullptr;
|
void* m_pWorkspace = nullptr;
|
||||||
void* m_pLayer = nullptr;
|
void* m_pLayer = nullptr;
|
||||||
|
@ -271,8 +148,8 @@ class CAnimatedVariable {
|
||||||
|
|
||||||
std::chrono::system_clock::time_point animationBegin;
|
std::chrono::system_clock::time_point animationBegin;
|
||||||
|
|
||||||
ANIMATEDVARTYPE m_eVarType = AVARTYPE_INVALID;
|
|
||||||
AVARDAMAGEPOLICY m_eDamagePolicy = AVARDAMAGE_NONE;
|
AVARDAMAGEPOLICY m_eDamagePolicy = AVARDAMAGE_NONE;
|
||||||
|
ANIMATEDVARTYPE m_Type;
|
||||||
|
|
||||||
bool m_bRemoveEndAfterRan = true;
|
bool m_bRemoveEndAfterRan = true;
|
||||||
bool m_bRemoveBeginAfterRan = true;
|
bool m_bRemoveBeginAfterRan = true;
|
||||||
|
@ -281,7 +158,9 @@ class CAnimatedVariable {
|
||||||
std::function<void(void* thisptr)> m_fUpdateCallback;
|
std::function<void(void* thisptr)> m_fUpdateCallback;
|
||||||
|
|
||||||
bool m_bIsConnectedToActive = false;
|
bool m_bIsConnectedToActive = false;
|
||||||
|
|
||||||
void connectToActive();
|
void connectToActive();
|
||||||
|
|
||||||
void disconnectFromActive();
|
void disconnectFromActive();
|
||||||
|
|
||||||
// methods
|
// methods
|
||||||
|
@ -314,3 +193,85 @@ class CAnimatedVariable {
|
||||||
friend struct SLayerSurface;
|
friend struct SLayerSurface;
|
||||||
friend class CHyprRenderer;
|
friend class CHyprRenderer;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <Animable VarType>
|
||||||
|
class CAnimatedVariable : public CBaseAnimatedVariable {
|
||||||
|
public:
|
||||||
|
CAnimatedVariable() : CBaseAnimatedVariable(typeToANIMATEDVARTYPE<VarType>) {} // dummy var
|
||||||
|
|
||||||
|
void create(const VarType& value, SAnimationPropertyConfig* pAnimConfig, void* pWindow, AVARDAMAGEPOLICY policy) {
|
||||||
|
create(pAnimConfig, pWindow, policy);
|
||||||
|
m_Value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
using CBaseAnimatedVariable::create;
|
||||||
|
|
||||||
|
CAnimatedVariable(const CAnimatedVariable&) = delete;
|
||||||
|
CAnimatedVariable(CAnimatedVariable&&) = delete;
|
||||||
|
CAnimatedVariable& operator=(const CAnimatedVariable&) = delete;
|
||||||
|
CAnimatedVariable& operator=(CAnimatedVariable&&) = delete;
|
||||||
|
|
||||||
|
~CAnimatedVariable() = default;
|
||||||
|
|
||||||
|
// gets the current vector value (real time)
|
||||||
|
const VarType& value() const {
|
||||||
|
return m_Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// gets the goal vector value
|
||||||
|
const VarType& goal() const {
|
||||||
|
return m_Goal;
|
||||||
|
}
|
||||||
|
|
||||||
|
CAnimatedVariable& operator=(const VarType& v) {
|
||||||
|
if (v == m_Goal)
|
||||||
|
return *this;
|
||||||
|
|
||||||
|
m_Goal = v;
|
||||||
|
animationBegin = std::chrono::system_clock::now();
|
||||||
|
m_Begun = m_Value;
|
||||||
|
|
||||||
|
onAnimationBegin();
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sets the actual stored value, without affecting the goal, but resets the timer
|
||||||
|
void setValue(const VarType& v) {
|
||||||
|
if (v == m_Value)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_Value = v;
|
||||||
|
animationBegin = std::chrono::system_clock::now();
|
||||||
|
m_Begun = m_Value;
|
||||||
|
|
||||||
|
onAnimationBegin();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sets the actual value and goal
|
||||||
|
void setValueAndWarp(const VarType& v) {
|
||||||
|
m_Goal = v;
|
||||||
|
warp();
|
||||||
|
}
|
||||||
|
|
||||||
|
void warp(bool endCallback = true) override {
|
||||||
|
m_Value = m_Goal;
|
||||||
|
|
||||||
|
m_bIsBeingAnimated = false;
|
||||||
|
|
||||||
|
if (endCallback)
|
||||||
|
onAnimationEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
VarType m_Value{};
|
||||||
|
VarType m_Goal{};
|
||||||
|
VarType m_Begun{};
|
||||||
|
|
||||||
|
// owners
|
||||||
|
|
||||||
|
friend class CAnimationManager;
|
||||||
|
friend class CWorkspace;
|
||||||
|
friend struct SLayerSurface;
|
||||||
|
friend class CHyprRenderer;
|
||||||
|
};
|
||||||
|
|
|
@ -1,4 +1,8 @@
|
||||||
#include "Box.hpp"
|
#include "Box.hpp"
|
||||||
|
|
||||||
|
#include <limits>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
wlr_box CBox::wlr() {
|
wlr_box CBox::wlr() {
|
||||||
CBox rounded = roundInternal();
|
CBox rounded = roundInternal();
|
||||||
m_bWlrBox = wlr_box{(int)rounded.x, (int)rounded.y, (int)rounded.w, (int)rounded.h};
|
m_bWlrBox = wlr_box{(int)rounded.x, (int)rounded.y, (int)rounded.w, (int)rounded.h};
|
||||||
|
@ -105,6 +109,13 @@ CBox& CBox::expand(const double& value) {
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CBox& CBox::noNegativeSize() {
|
||||||
|
std::clamp(w, 0.0, std::numeric_limits<double>::infinity());
|
||||||
|
std::clamp(h, 0.0, std::numeric_limits<double>::infinity());
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
CBox CBox::roundInternal() {
|
CBox CBox::roundInternal() {
|
||||||
float newW = x + w - std::floor(x);
|
float newW = x + w - std::floor(x);
|
||||||
float newH = y + h - std::floor(y);
|
float newH = y + h - std::floor(y);
|
||||||
|
|
|
@ -51,6 +51,7 @@ class CBox {
|
||||||
CBox& transform(const wl_output_transform t, double w, double h);
|
CBox& transform(const wl_output_transform t, double w, double h);
|
||||||
CBox& addExtents(const SWindowDecorationExtents& e);
|
CBox& addExtents(const SWindowDecorationExtents& e);
|
||||||
CBox& expand(const double& value);
|
CBox& expand(const double& value);
|
||||||
|
CBox& noNegativeSize();
|
||||||
|
|
||||||
CBox copy() const;
|
CBox copy() const;
|
||||||
|
|
||||||
|
@ -73,6 +74,8 @@ class CBox {
|
||||||
double height;
|
double height;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
double rot = 0; /* rad, ccw */
|
||||||
|
|
||||||
//
|
//
|
||||||
bool operator==(const CBox& rhs) const {
|
bool operator==(const CBox& rhs) const {
|
||||||
return x == rhs.x && y == rhs.y && w == rhs.w && h == rhs.h;
|
return x == rhs.x && y == rhs.y && w == rhs.w && h == rhs.h;
|
||||||
|
|
|
@ -159,6 +159,13 @@ void addWLSignal(wl_signal* pSignal, wl_listener* pListener, void* pOwner, const
|
||||||
Debug::log(LOG, "Registered signal for owner {:x}: {:x} -> {:x} (owner: {})", (uintptr_t)pOwner, (uintptr_t)pSignal, (uintptr_t)pListener, ownerString);
|
Debug::log(LOG, "Registered signal for owner {:x}: {:x} -> {:x} (owner: {})", (uintptr_t)pOwner, (uintptr_t)pSignal, (uintptr_t)pListener, ownerString);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void removeWLSignal(wl_listener* pListener) {
|
||||||
|
wl_list_remove(&pListener->link);
|
||||||
|
wl_list_init(&pListener->link);
|
||||||
|
|
||||||
|
Debug::log(LOG, "Removed listener {:x}", (uintptr_t)pListener);
|
||||||
|
}
|
||||||
|
|
||||||
void handleNoop(struct wl_listener* listener, void* data) {
|
void handleNoop(struct wl_listener* listener, void* data) {
|
||||||
// Do nothing
|
// Do nothing
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@ struct SCallstackFrameInfo {
|
||||||
|
|
||||||
std::string absolutePath(const std::string&, const std::string&);
|
std::string absolutePath(const std::string&, const std::string&);
|
||||||
void addWLSignal(wl_signal*, wl_listener*, void* pOwner, const std::string& ownerString);
|
void addWLSignal(wl_signal*, wl_listener*, void* pOwner, const std::string& ownerString);
|
||||||
|
void removeWLSignal(wl_listener*);
|
||||||
std::string escapeJSONStrings(const std::string& str);
|
std::string escapeJSONStrings(const std::string& str);
|
||||||
std::string removeBeginEndSpacesTabs(std::string);
|
std::string removeBeginEndSpacesTabs(std::string);
|
||||||
bool isNumber(const std::string&, bool allowfloat = false);
|
bool isNumber(const std::string&, bool allowfloat = false);
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
#include "Monitor.hpp"
|
#include "Monitor.hpp"
|
||||||
|
|
||||||
|
#include "MiscFunctions.hpp"
|
||||||
|
|
||||||
#include "../Compositor.hpp"
|
#include "../Compositor.hpp"
|
||||||
|
|
||||||
int ratHandler(void* data) {
|
int ratHandler(void* data) {
|
||||||
|
@ -8,7 +10,7 @@ int ratHandler(void* data) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
CMonitor::CMonitor() {
|
CMonitor::CMonitor() : state(this) {
|
||||||
wlr_damage_ring_init(&damage);
|
wlr_damage_ring_init(&damage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,8 +45,8 @@ void CMonitor::onConnect(bool noRule) {
|
||||||
tearingState.canTear = wlr_backend_is_drm(output->backend); // tearing only works on drm
|
tearingState.canTear = wlr_backend_is_drm(output->backend); // tearing only works on drm
|
||||||
|
|
||||||
if (m_bEnabled) {
|
if (m_bEnabled) {
|
||||||
wlr_output_enable(output, 1);
|
wlr_output_state_set_enabled(state.wlr(), true);
|
||||||
wlr_output_commit(output);
|
state.commit();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,17 +56,21 @@ void CMonitor::onConnect(bool noRule) {
|
||||||
// remove comma character from description. This allow monitor specific rules to work on monitor with comma on their description
|
// remove comma character from description. This allow monitor specific rules to work on monitor with comma on their description
|
||||||
szDescription.erase(std::remove(szDescription.begin(), szDescription.end(), ','), szDescription.end());
|
szDescription.erase(std::remove(szDescription.begin(), szDescription.end(), ','), szDescription.end());
|
||||||
|
|
||||||
|
// field is backwards-compatible with intended usage of `szDescription` but excludes the parenthesized DRM node name suffix
|
||||||
|
szShortDescription =
|
||||||
|
removeBeginEndSpacesTabs(std::format("{} {} {}", output->make ? output->make : "", output->model ? output->model : "", output->serial ? output->serial : ""));
|
||||||
|
|
||||||
if (!wlr_backend_is_drm(output->backend))
|
if (!wlr_backend_is_drm(output->backend))
|
||||||
createdByUser = true; // should be true. WL, X11 and Headless backends should be addable / removable
|
createdByUser = true; // should be true. WL, X11 and Headless backends should be addable / removable
|
||||||
|
|
||||||
// get monitor rule that matches
|
// get monitor rule that matches
|
||||||
SMonitorRule monitorRule = g_pConfigManager->getMonitorRuleFor(output->name, output->description ? output->description : "");
|
SMonitorRule monitorRule = g_pConfigManager->getMonitorRuleFor(*this);
|
||||||
|
|
||||||
// if it's disabled, disable and ignore
|
// if it's disabled, disable and ignore
|
||||||
if (monitorRule.disabled) {
|
if (monitorRule.disabled) {
|
||||||
|
|
||||||
wlr_output_set_scale(output, 1);
|
wlr_output_state_set_scale(state.wlr(), 1);
|
||||||
wlr_output_set_transform(output, WL_OUTPUT_TRANSFORM_NORMAL);
|
wlr_output_state_set_transform(state.wlr(), WL_OUTPUT_TRANSFORM_NORMAL);
|
||||||
|
|
||||||
auto PREFSTATE = wlr_output_preferred_mode(output);
|
auto PREFSTATE = wlr_output_preferred_mode(output);
|
||||||
|
|
||||||
|
@ -72,9 +78,9 @@ void CMonitor::onConnect(bool noRule) {
|
||||||
wlr_output_mode* mode;
|
wlr_output_mode* mode;
|
||||||
|
|
||||||
wl_list_for_each(mode, &output->modes, link) {
|
wl_list_for_each(mode, &output->modes, link) {
|
||||||
wlr_output_set_mode(output, PREFSTATE);
|
wlr_output_state_set_mode(state.wlr(), mode);
|
||||||
|
|
||||||
if (!wlr_output_test(output))
|
if (!wlr_output_test_state(output, state.wlr()))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
PREFSTATE = mode;
|
PREFSTATE = mode;
|
||||||
|
@ -83,13 +89,13 @@ void CMonitor::onConnect(bool noRule) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PREFSTATE)
|
if (PREFSTATE)
|
||||||
wlr_output_set_mode(output, PREFSTATE);
|
wlr_output_state_set_mode(state.wlr(), PREFSTATE);
|
||||||
else
|
else
|
||||||
Debug::log(WARN, "No mode found for disabled output {}", output->name);
|
Debug::log(WARN, "No mode found for disabled output {}", output->name);
|
||||||
|
|
||||||
wlr_output_enable(output, 0);
|
wlr_output_state_set_enabled(state.wlr(), 0);
|
||||||
|
|
||||||
if (!wlr_output_commit(output))
|
if (!state.commit())
|
||||||
Debug::log(ERR, "Couldn't commit disabled state on output {}", output->name);
|
Debug::log(ERR, "Couldn't commit disabled state on output {}", output->name);
|
||||||
|
|
||||||
m_bEnabled = false;
|
m_bEnabled = false;
|
||||||
|
@ -130,13 +136,28 @@ void CMonitor::onConnect(bool noRule) {
|
||||||
|
|
||||||
m_bEnabled = true;
|
m_bEnabled = true;
|
||||||
|
|
||||||
wlr_output_enable(output, 1);
|
wlr_output_state_set_enabled(state.wlr(), 1);
|
||||||
|
|
||||||
// set mode, also applies
|
// set mode, also applies
|
||||||
if (!noRule)
|
if (!noRule)
|
||||||
g_pHyprRenderer->applyMonitorRule(this, &monitorRule, true);
|
g_pHyprRenderer->applyMonitorRule(this, &monitorRule, true);
|
||||||
|
|
||||||
wlr_output_commit(output);
|
for (const auto& PTOUCHDEV : g_pInputManager->m_lTouchDevices) {
|
||||||
|
if (matchesStaticSelector(PTOUCHDEV.boundOutput)) {
|
||||||
|
Debug::log(LOG, "Binding touch device {} to output {}", PTOUCHDEV.name, szName);
|
||||||
|
wlr_cursor_map_input_to_output(g_pCompositor->m_sWLRCursor, PTOUCHDEV.pWlrDevice, output);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& PTABLET : g_pInputManager->m_lTablets) {
|
||||||
|
if (matchesStaticSelector(PTABLET.boundOutput)) {
|
||||||
|
Debug::log(LOG, "Binding tablet {} to output {}", PTABLET.name, szName);
|
||||||
|
wlr_cursor_map_input_to_output(g_pCompositor->m_sWLRCursor, PTABLET.wlrDevice, output);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!state.commit())
|
||||||
|
Debug::log(WARN, "wlr_output_commit_state failed in CMonitor::onCommit");
|
||||||
|
|
||||||
wlr_damage_ring_set_bounds(&damage, vecTransformedSize.x, vecTransformedSize.y);
|
wlr_damage_ring_set_bounds(&damage, vecTransformedSize.x, vecTransformedSize.y);
|
||||||
|
|
||||||
|
@ -162,6 +183,7 @@ void CMonitor::onConnect(bool noRule) {
|
||||||
//
|
//
|
||||||
|
|
||||||
g_pEventManager->postEvent(SHyprIPCEvent{"monitoradded", szName});
|
g_pEventManager->postEvent(SHyprIPCEvent{"monitoradded", szName});
|
||||||
|
g_pEventManager->postEvent(SHyprIPCEvent{"monitoraddedv2", std::format("{},{},{}", ID, szName, szShortDescription)});
|
||||||
EMIT_HOOK_EVENT("monitorAdded", this);
|
EMIT_HOOK_EVENT("monitorAdded", this);
|
||||||
|
|
||||||
if (!g_pCompositor->m_pLastMonitor) // set the last monitor if it isnt set yet
|
if (!g_pCompositor->m_pLastMonitor) // set the last monitor if it isnt set yet
|
||||||
|
@ -283,9 +305,10 @@ void CMonitor::onDisconnect(bool destroy) {
|
||||||
if (!destroy)
|
if (!destroy)
|
||||||
wlr_output_layout_remove(g_pCompositor->m_sWLROutputLayout, output);
|
wlr_output_layout_remove(g_pCompositor->m_sWLROutputLayout, output);
|
||||||
|
|
||||||
wlr_output_enable(output, false);
|
wlr_output_state_set_enabled(state.wlr(), false);
|
||||||
|
|
||||||
wlr_output_commit(output);
|
if (!state.commit())
|
||||||
|
Debug::log(WARN, "wlr_output_commit_state failed in CMonitor::onDisconnect");
|
||||||
|
|
||||||
if (g_pCompositor->m_pLastMonitor == this)
|
if (g_pCompositor->m_pLastMonitor == this)
|
||||||
g_pCompositor->setActiveMonitor(BACKUPMON);
|
g_pCompositor->setActiveMonitor(BACKUPMON);
|
||||||
|
@ -307,13 +330,11 @@ void CMonitor::onDisconnect(bool destroy) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMonitor::addDamage(const pixman_region32_t* rg) {
|
void CMonitor::addDamage(const pixman_region32_t* rg) {
|
||||||
static auto* const PZOOMFACTOR = &g_pConfigManager->getConfigValuePtr("misc:cursor_zoom_factor")->floatValue;
|
static auto* const PZOOMFACTOR = (Hyprlang::FLOAT* const*)g_pConfigManager->getConfigValuePtr("misc:cursor_zoom_factor");
|
||||||
if (*PZOOMFACTOR != 1.f && g_pCompositor->getMonitorFromCursor() == this) {
|
if (**PZOOMFACTOR != 1.f && g_pCompositor->getMonitorFromCursor() == this) {
|
||||||
wlr_damage_ring_add_whole(&damage);
|
wlr_damage_ring_add_whole(&damage);
|
||||||
g_pCompositor->scheduleFrameForMonitor(this);
|
g_pCompositor->scheduleFrameForMonitor(this);
|
||||||
}
|
} else if (wlr_damage_ring_add(&damage, rg))
|
||||||
|
|
||||||
if (wlr_damage_ring_add(&damage, rg))
|
|
||||||
g_pCompositor->scheduleFrameForMonitor(this);
|
g_pCompositor->scheduleFrameForMonitor(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -322,8 +343,8 @@ void CMonitor::addDamage(const CRegion* rg) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMonitor::addDamage(const CBox* box) {
|
void CMonitor::addDamage(const CBox* box) {
|
||||||
static auto* const PZOOMFACTOR = &g_pConfigManager->getConfigValuePtr("misc:cursor_zoom_factor")->floatValue;
|
static auto* const PZOOMFACTOR = (Hyprlang::FLOAT* const*)g_pConfigManager->getConfigValuePtr("misc:cursor_zoom_factor");
|
||||||
if (*PZOOMFACTOR != 1.f && g_pCompositor->getMonitorFromCursor() == this) {
|
if (**PZOOMFACTOR != 1.f && g_pCompositor->getMonitorFromCursor() == this) {
|
||||||
wlr_damage_ring_add_whole(&damage);
|
wlr_damage_ring_add_whole(&damage);
|
||||||
g_pCompositor->scheduleFrameForMonitor(this);
|
g_pCompositor->scheduleFrameForMonitor(this);
|
||||||
}
|
}
|
||||||
|
@ -336,6 +357,19 @@ bool CMonitor::isMirror() {
|
||||||
return pMirrorOf != nullptr;
|
return pMirrorOf != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CMonitor::matchesStaticSelector(const std::string& selector) const {
|
||||||
|
if (selector.starts_with("desc:")) {
|
||||||
|
// match by description
|
||||||
|
const auto DESCRIPTIONSELECTOR = selector.substr(5);
|
||||||
|
const auto DESCRIPTION = removeBeginEndSpacesTabs(szDescription.substr(0, szDescription.find_first_of('(')));
|
||||||
|
|
||||||
|
return DESCRIPTIONSELECTOR == szDescription || DESCRIPTIONSELECTOR == DESCRIPTION;
|
||||||
|
} else {
|
||||||
|
// match by selector
|
||||||
|
return szName == selector;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int CMonitor::findAvailableDefaultWS() {
|
int CMonitor::findAvailableDefaultWS() {
|
||||||
for (size_t i = 1; i < INT32_MAX; ++i) {
|
for (size_t i = 1; i < INT32_MAX; ++i) {
|
||||||
if (g_pCompositor->getWorkspaceByID(i))
|
if (g_pCompositor->getWorkspaceByID(i))
|
||||||
|
@ -415,7 +449,7 @@ void CMonitor::setMirror(const std::string& mirrorOf) {
|
||||||
pMirrorOf = nullptr;
|
pMirrorOf = nullptr;
|
||||||
|
|
||||||
// set rule
|
// set rule
|
||||||
const auto RULE = g_pConfigManager->getMonitorRuleFor(this->szName, this->output->description ? this->output->description : "");
|
const auto RULE = g_pConfigManager->getMonitorRuleFor(*this);
|
||||||
|
|
||||||
vecPosition = RULE.offset;
|
vecPosition = RULE.offset;
|
||||||
|
|
||||||
|
@ -502,7 +536,7 @@ float CMonitor::getDefaultScale() {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMonitor::changeWorkspace(CWorkspace* const pWorkspace, bool internal, bool noMouseMove) {
|
void CMonitor::changeWorkspace(CWorkspace* const pWorkspace, bool internal, bool noMouseMove, bool noFocus) {
|
||||||
if (!pWorkspace)
|
if (!pWorkspace)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -533,13 +567,13 @@ void CMonitor::changeWorkspace(CWorkspace* const pWorkspace, bool internal, bool
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!g_pCompositor->m_pLastMonitor->specialWorkspaceID) {
|
if (!noFocus && !g_pCompositor->m_pLastMonitor->specialWorkspaceID) {
|
||||||
static auto* const PFOLLOWMOUSE = &g_pConfigManager->getConfigValuePtr("input:follow_mouse")->intValue;
|
static auto* const PFOLLOWMOUSE = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("input:follow_mouse");
|
||||||
CWindow* pWindow = pWorkspace->getLastFocusedWindow();
|
CWindow* pWindow = pWorkspace->getLastFocusedWindow();
|
||||||
|
|
||||||
if (!pWindow) {
|
if (!pWindow) {
|
||||||
if (*PFOLLOWMOUSE == 1)
|
if (**PFOLLOWMOUSE == 1)
|
||||||
pWindow = g_pCompositor->vectorToWindowIdeal(g_pInputManager->getMouseCoordsInternal());
|
pWindow = g_pCompositor->vectorToWindowUnified(g_pInputManager->getMouseCoordsInternal(), RESERVED_EXTENTS | INPUT_EXTENTS | ALLOW_FLOATING);
|
||||||
|
|
||||||
if (!pWindow)
|
if (!pWindow)
|
||||||
pWindow = g_pCompositor->getTopLeftWindowOnWorkspace(pWorkspace->m_iID);
|
pWindow = g_pCompositor->getTopLeftWindowOnWorkspace(pWorkspace->m_iID);
|
||||||
|
@ -569,8 +603,8 @@ void CMonitor::changeWorkspace(CWorkspace* const pWorkspace, bool internal, bool
|
||||||
g_pCompositor->updateSuspendedStates();
|
g_pCompositor->updateSuspendedStates();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMonitor::changeWorkspace(const int& id, bool internal) {
|
void CMonitor::changeWorkspace(const int& id, bool internal, bool noMouseMove, bool noFocus) {
|
||||||
changeWorkspace(g_pCompositor->getWorkspaceByID(id), internal);
|
changeWorkspace(g_pCompositor->getWorkspaceByID(id), internal, noMouseMove, noFocus);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMonitor::setSpecialWorkspace(CWorkspace* const pWorkspace) {
|
void CMonitor::setSpecialWorkspace(CWorkspace* const pWorkspace) {
|
||||||
|
@ -621,17 +655,17 @@ void CMonitor::setSpecialWorkspace(CWorkspace* const pWorkspace) {
|
||||||
for (auto& w : g_pCompositor->m_vWindows) {
|
for (auto& w : g_pCompositor->m_vWindows) {
|
||||||
if (w->m_iWorkspaceID == pWorkspace->m_iID) {
|
if (w->m_iWorkspaceID == pWorkspace->m_iID) {
|
||||||
w->m_iMonitorID = ID;
|
w->m_iMonitorID = ID;
|
||||||
w->updateSurfaceOutputs();
|
w->updateSurfaceScaleTransformDetails();
|
||||||
|
|
||||||
const auto MIDDLE = w->middle();
|
const auto MIDDLE = w->middle();
|
||||||
if (w->m_bIsFloating && !VECINRECT(MIDDLE, vecPosition.x, vecPosition.y, vecPosition.x + vecSize.x, vecPosition.y + vecSize.y) && w->m_iX11Type != 2) {
|
if (w->m_bIsFloating && !VECINRECT(MIDDLE, vecPosition.x, vecPosition.y, vecPosition.x + vecSize.x, vecPosition.y + vecSize.y) && w->m_iX11Type != 2) {
|
||||||
// if it's floating and the middle isnt on the current mon, move it to the center
|
// if it's floating and the middle isnt on the current mon, move it to the center
|
||||||
const auto PMONFROMMIDDLE = g_pCompositor->getMonitorFromVector(MIDDLE);
|
const auto PMONFROMMIDDLE = g_pCompositor->getMonitorFromVector(MIDDLE);
|
||||||
Vector2D pos = w->m_vRealPosition.goalv();
|
Vector2D pos = w->m_vRealPosition.goal();
|
||||||
if (!VECINRECT(MIDDLE, PMONFROMMIDDLE->vecPosition.x, PMONFROMMIDDLE->vecPosition.y, PMONFROMMIDDLE->vecPosition.x + PMONFROMMIDDLE->vecSize.x,
|
if (!VECINRECT(MIDDLE, PMONFROMMIDDLE->vecPosition.x, PMONFROMMIDDLE->vecPosition.y, PMONFROMMIDDLE->vecPosition.x + PMONFROMMIDDLE->vecSize.x,
|
||||||
PMONFROMMIDDLE->vecPosition.y + PMONFROMMIDDLE->vecSize.y)) {
|
PMONFROMMIDDLE->vecPosition.y + PMONFROMMIDDLE->vecSize.y)) {
|
||||||
// not on any monitor, center
|
// not on any monitor, center
|
||||||
pos = middle() / 2.f - w->m_vRealSize.goalv() / 2.f;
|
pos = middle() / 2.f - w->m_vRealSize.goal() / 2.f;
|
||||||
} else
|
} else
|
||||||
pos = pos - PMONFROMMIDDLE->vecPosition + vecPosition;
|
pos = pos - PMONFROMMIDDLE->vecPosition + vecPosition;
|
||||||
|
|
||||||
|
@ -678,3 +712,32 @@ void CMonitor::updateMatrix() {
|
||||||
wlr_matrix_translate(projMatrix.data(), -vecTransformedSize.x / 2.0, -vecTransformedSize.y / 2.0);
|
wlr_matrix_translate(projMatrix.data(), -vecTransformedSize.x / 2.0, -vecTransformedSize.y / 2.0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CMonitorState::CMonitorState(CMonitor* owner) {
|
||||||
|
m_pOwner = owner;
|
||||||
|
wlr_output_state_init(&m_state);
|
||||||
|
}
|
||||||
|
|
||||||
|
CMonitorState::~CMonitorState() {
|
||||||
|
wlr_output_state_finish(&m_state);
|
||||||
|
}
|
||||||
|
|
||||||
|
wlr_output_state* CMonitorState::wlr() {
|
||||||
|
return &m_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMonitorState::clear() {
|
||||||
|
wlr_output_state_finish(&m_state);
|
||||||
|
m_state = {0};
|
||||||
|
wlr_output_state_init(&m_state);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CMonitorState::commit() {
|
||||||
|
bool ret = wlr_output_commit_state(m_pOwner->output, &m_state);
|
||||||
|
clear();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CMonitorState::test() {
|
||||||
|
return wlr_output_test_state(m_pOwner->output, &m_state);
|
||||||
|
}
|
||||||
|
|
|
@ -25,6 +25,25 @@ struct SMonitorRule {
|
||||||
std::optional<int> vrr;
|
std::optional<int> vrr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class CMonitor;
|
||||||
|
|
||||||
|
// Class for wrapping the wlr state
|
||||||
|
class CMonitorState {
|
||||||
|
public:
|
||||||
|
CMonitorState(CMonitor* owner);
|
||||||
|
~CMonitorState();
|
||||||
|
|
||||||
|
wlr_output_state* wlr();
|
||||||
|
void clear();
|
||||||
|
// commit() will also clear()
|
||||||
|
bool commit();
|
||||||
|
bool test();
|
||||||
|
|
||||||
|
private:
|
||||||
|
wlr_output_state m_state = {0};
|
||||||
|
CMonitor* m_pOwner;
|
||||||
|
};
|
||||||
|
|
||||||
class CMonitor {
|
class CMonitor {
|
||||||
public:
|
public:
|
||||||
CMonitor();
|
CMonitor();
|
||||||
|
@ -43,49 +62,51 @@ class CMonitor {
|
||||||
float setScale = 1; // scale set by cfg
|
float setScale = 1; // scale set by cfg
|
||||||
float scale = 1; // real scale
|
float scale = 1; // real scale
|
||||||
|
|
||||||
std::string szName = "";
|
std::string szName = "";
|
||||||
std::string szDescription = "";
|
std::string szDescription = "";
|
||||||
|
std::string szShortDescription = "";
|
||||||
|
|
||||||
Vector2D vecReservedTopLeft = Vector2D(0, 0);
|
Vector2D vecReservedTopLeft = Vector2D(0, 0);
|
||||||
Vector2D vecReservedBottomRight = Vector2D(0, 0);
|
Vector2D vecReservedBottomRight = Vector2D(0, 0);
|
||||||
|
|
||||||
drmModeModeInfo customDrmMode = {};
|
drmModeModeInfo customDrmMode = {};
|
||||||
|
|
||||||
|
CMonitorState state;
|
||||||
|
|
||||||
// WLR stuff
|
// WLR stuff
|
||||||
wlr_damage_ring damage;
|
wlr_damage_ring damage;
|
||||||
wlr_output* output = nullptr;
|
wlr_output* output = nullptr;
|
||||||
float refreshRate = 60;
|
float refreshRate = 60;
|
||||||
int framesToSkip = 0;
|
int framesToSkip = 0;
|
||||||
int forceFullFrames = 0;
|
int forceFullFrames = 0;
|
||||||
bool noFrameSchedule = false;
|
bool noFrameSchedule = false;
|
||||||
bool scheduledRecalc = false;
|
bool scheduledRecalc = false;
|
||||||
wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
||||||
bool gammaChanged = false;
|
bool gammaChanged = false;
|
||||||
float xwaylandScale = 1.f;
|
float xwaylandScale = 1.f;
|
||||||
std::array<float, 9> projMatrix = {0};
|
std::array<float, 9> projMatrix = {0};
|
||||||
|
std::optional<Vector2D> forceSize;
|
||||||
|
|
||||||
bool dpmsStatus = true;
|
bool dpmsStatus = true;
|
||||||
bool vrrActive = false; // this can be TRUE even if VRR is not active in the case that this display does not support it.
|
bool vrrActive = false; // this can be TRUE even if VRR is not active in the case that this display does not support it.
|
||||||
bool enabled10bit = false; // as above, this can be TRUE even if 10 bit failed.
|
bool enabled10bit = false; // as above, this can be TRUE even if 10 bit failed.
|
||||||
bool createdByUser = false;
|
bool createdByUser = false;
|
||||||
uint32_t drmFormat = DRM_FORMAT_INVALID;
|
uint32_t drmFormat = DRM_FORMAT_INVALID;
|
||||||
bool isUnsafeFallback = false;
|
bool isUnsafeFallback = false;
|
||||||
|
|
||||||
bool pendingFrame = false; // if we schedule a frame during rendering, reschedule it after
|
bool pendingFrame = false; // if we schedule a frame during rendering, reschedule it after
|
||||||
bool renderingActive = false;
|
bool renderingActive = false;
|
||||||
|
|
||||||
wl_event_source* renderTimer = nullptr; // for RAT
|
wl_event_source* renderTimer = nullptr; // for RAT
|
||||||
bool RATScheduled = false;
|
bool RATScheduled = false;
|
||||||
CTimer lastPresentationTimer;
|
CTimer lastPresentationTimer;
|
||||||
|
|
||||||
SMonitorRule activeMonitorRule;
|
SMonitorRule activeMonitorRule;
|
||||||
|
|
||||||
// mirroring
|
// mirroring
|
||||||
CMonitor* pMirrorOf = nullptr;
|
CMonitor* pMirrorOf = nullptr;
|
||||||
std::vector<CMonitor*> mirrors;
|
std::vector<CMonitor*> mirrors;
|
||||||
|
|
||||||
CRegion lastFrameDamage; // stores last frame damage
|
|
||||||
|
|
||||||
// for tearing
|
// for tearing
|
||||||
CWindow* solitaryClient = nullptr;
|
CWindow* solitaryClient = nullptr;
|
||||||
|
|
||||||
|
@ -119,9 +140,10 @@ class CMonitor {
|
||||||
void addDamage(const CBox* box);
|
void addDamage(const CBox* box);
|
||||||
void setMirror(const std::string&);
|
void setMirror(const std::string&);
|
||||||
bool isMirror();
|
bool isMirror();
|
||||||
|
bool matchesStaticSelector(const std::string& selector) const;
|
||||||
float getDefaultScale();
|
float getDefaultScale();
|
||||||
void changeWorkspace(CWorkspace* const pWorkspace, bool internal = false, bool noMouseMove = false);
|
void changeWorkspace(CWorkspace* const pWorkspace, bool internal = false, bool noMouseMove = false, bool noFocus = false);
|
||||||
void changeWorkspace(const int& id, bool internal = false);
|
void changeWorkspace(const int& id, bool internal = false, bool noMouseMove = false, bool noFocus = false);
|
||||||
void setSpecialWorkspace(CWorkspace* const pWorkspace);
|
void setSpecialWorkspace(CWorkspace* const pWorkspace);
|
||||||
void setSpecialWorkspace(const int& id);
|
void setSpecialWorkspace(const int& id);
|
||||||
void moveTo(const Vector2D& pos);
|
void moveTo(const Vector2D& pos);
|
||||||
|
|
|
@ -112,6 +112,11 @@ CRegion& CRegion::scale(float scale) {
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CRegion& CRegion::scale(const Vector2D& scale) {
|
||||||
|
wlr_region_scale_xy(&m_rRegion, &m_rRegion, scale.x, scale.y);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<pixman_box32_t> CRegion::getRects() const {
|
std::vector<pixman_box32_t> CRegion::getRects() const {
|
||||||
std::vector<pixman_box32_t> result;
|
std::vector<pixman_box32_t> result;
|
||||||
|
|
||||||
|
|
|
@ -49,6 +49,7 @@ class CRegion {
|
||||||
CRegion& invert(pixman_box32_t* box);
|
CRegion& invert(pixman_box32_t* box);
|
||||||
CRegion& invert(const CBox& box);
|
CRegion& invert(const CBox& box);
|
||||||
CRegion& scale(float scale);
|
CRegion& scale(float scale);
|
||||||
|
CRegion& scale(const Vector2D& scale);
|
||||||
CBox getExtents();
|
CBox getExtents();
|
||||||
bool containsPoint(const Vector2D& vec) const;
|
bool containsPoint(const Vector2D& vec) const;
|
||||||
bool empty() const;
|
bool empty() const;
|
||||||
|
@ -57,7 +58,8 @@ class CRegion {
|
||||||
|
|
||||||
std::vector<pixman_box32_t> getRects() const;
|
std::vector<pixman_box32_t> getRects() const;
|
||||||
|
|
||||||
pixman_region32_t* pixman() {
|
//
|
||||||
|
pixman_region32_t* pixman() {
|
||||||
return &m_rRegion;
|
return &m_rRegion;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,21 @@ inline const std::vector<std::string> SPLASHES = {
|
||||||
"Compile, wait for 20 minutes, notice a new commit, compile again.",
|
"Compile, wait for 20 minutes, notice a new commit, compile again.",
|
||||||
"To rice, or not to rice, that is the question.",
|
"To rice, or not to rice, that is the question.",
|
||||||
"Now available on Fedora!",
|
"Now available on Fedora!",
|
||||||
|
"\"Hyprland is so good it starts with a capital letter\" - Hazel",
|
||||||
|
"\"please make this message a splash\" - eriedaberrie",
|
||||||
|
"\"the only wayland compositor powered by fried chicken\" - raf",
|
||||||
|
"\"This will never get into Hyprland\" - Flafy",
|
||||||
|
"\"Hyprland only gives you up on -git\" - fazzi",
|
||||||
|
"Segmentation fault (core dumped)",
|
||||||
|
"\"disabling hyprland logo is a war crime\" - vaxry",
|
||||||
|
"some basic startup code",
|
||||||
|
"\"I think I am addicted to hyprland\" - mathisbuilder",
|
||||||
|
"\"hyprland is the most important package in the arch repos\" - jacekpoz",
|
||||||
|
"Thanks Brodie!",
|
||||||
|
"Thanks fufexan!",
|
||||||
|
"Thanks raf!",
|
||||||
|
"You can't use --splash to change this message :)",
|
||||||
|
"Hyprland will overtake Gnome in popularity by [insert year]",
|
||||||
// music reference / quote section
|
// music reference / quote section
|
||||||
"J'remue le ciel, le jour, la nuit.",
|
"J'remue le ciel, le jour, la nuit.",
|
||||||
"aezakmi, aezakmi, aezakmi, aezakmi, aezakmi, aezakmi, aezakmi!",
|
"aezakmi, aezakmi, aezakmi, aezakmi, aezakmi, aezakmi, aezakmi!",
|
||||||
|
@ -26,23 +41,6 @@ inline const std::vector<std::string> SPLASHES = {
|
||||||
"I see a red door and I want it painted black.",
|
"I see a red door and I want it painted black.",
|
||||||
"Take on me, take me on...",
|
"Take on me, take me on...",
|
||||||
"You spin me right round baby right round",
|
"You spin me right round baby right round",
|
||||||
"Through the fire and the flames, we carry on!",
|
|
||||||
"Life could be a dream, sweetheart",
|
|
||||||
"We're off to never-never land",
|
|
||||||
"Just remember ALL CAPS when you spell the man name",
|
|
||||||
"The cake is a lie The cake is a lie The cake is a lie The cake is a lie",
|
|
||||||
"WE'RE SHAMELESS",
|
|
||||||
"Now I only want you gone",
|
|
||||||
"You Forget A Thousand Things Every Day Pal. Make Sure This Is One Of 'Em."
|
|
||||||
"The right man in the wrong place can make all the difference in the world."
|
|
||||||
"Truth Is, The Game Was Rigged From The Start."
|
|
||||||
"It's said war, war never changes. Men do, through the roads they walk."
|
|
||||||
"Victory shall be ours, it shall be swift, and it will be honest; purchased with blood."
|
|
||||||
"Patrolling the Mojave almost makes you wish for a nuclear winter."
|
|
||||||
"When life gives you lemons, don’t make lemonade…"
|
|
||||||
"You Picked The Wrong House, Fool!"
|
|
||||||
"I suck at life, but I bowl like an angel."
|
|
||||||
"Swaying to the symphony... of destruction!",
|
|
||||||
"Stayin' alive, stayin' alive",
|
"Stayin' alive, stayin' alive",
|
||||||
"Say no way, say no way ya, no way!",
|
"Say no way, say no way ya, no way!",
|
||||||
"Ground control to Major Tom...",
|
"Ground control to Major Tom...",
|
||||||
|
@ -79,4 +77,4 @@ inline const std::vector<std::string> SPLASHES = {
|
||||||
"The AUR packages always work, except for the times they don't.",
|
"The AUR packages always work, except for the times they don't.",
|
||||||
"Funny animation compositor woo"
|
"Funny animation compositor woo"
|
||||||
// clang-format on
|
// clang-format on
|
||||||
};
|
};
|
|
@ -1,311 +0,0 @@
|
||||||
#include "SubsurfaceTree.hpp"
|
|
||||||
#include "../events/Events.hpp"
|
|
||||||
#include "../Compositor.hpp"
|
|
||||||
|
|
||||||
void addSurfaceGlobalOffset(SSurfaceTreeNode* node, int* lx, int* ly) {
|
|
||||||
if (!node->pSurface || !node->pSurface->exists())
|
|
||||||
return;
|
|
||||||
|
|
||||||
*lx += node->pSurface->wlr()->current.dx;
|
|
||||||
*ly += node->pSurface->wlr()->current.dy;
|
|
||||||
|
|
||||||
if (node->offsetfn) {
|
|
||||||
// This is the root node
|
|
||||||
RASSERT(!node->pSubsurface, "Node had no subsurface!");
|
|
||||||
node->offsetfn(node->globalOffsetData, lx, ly);
|
|
||||||
} else {
|
|
||||||
RASSERT(node->pSubsurface, "Node had no subsurface!");
|
|
||||||
|
|
||||||
*lx += node->pSubsurface->pSubsurface->current.x;
|
|
||||||
*ly += node->pSubsurface->pSubsurface->current.y;
|
|
||||||
|
|
||||||
addSurfaceGlobalOffset(node->pParent, lx, ly);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SSurfaceTreeNode* createTree(wlr_surface* pSurface, CWindow* pWindow) {
|
|
||||||
const auto PNODE = &SubsurfaceTree::surfaceTreeNodes.emplace_back();
|
|
||||||
|
|
||||||
if (pSurface->data)
|
|
||||||
PNODE->pSurface = (CWLSurface*)pSurface->data;
|
|
||||||
else {
|
|
||||||
PNODE->pInternalSurface = pSurface;
|
|
||||||
PNODE->pSurface = &PNODE->pInternalSurface;
|
|
||||||
}
|
|
||||||
|
|
||||||
PNODE->pWindowOwner = pWindow;
|
|
||||||
|
|
||||||
PNODE->hyprListener_newSubsurface.initCallback(&pSurface->events.new_subsurface, &Events::listener_newSubsurfaceNode, PNODE, "SurfaceTreeNode");
|
|
||||||
PNODE->hyprListener_commit.initCallback(&pSurface->events.commit, &Events::listener_commitSubsurface, PNODE, "SurfaceTreeNode");
|
|
||||||
PNODE->hyprListener_destroy.initCallback(&pSurface->events.destroy, &Events::listener_destroySubsurfaceNode, PNODE, "SurfaceTreeNode");
|
|
||||||
|
|
||||||
wlr_subsurface* wlrSubsurface;
|
|
||||||
wl_list_for_each(wlrSubsurface, &pSurface->current.subsurfaces_below, current.link) {
|
|
||||||
Events::listener_newSubsurfaceNode(PNODE, wlrSubsurface);
|
|
||||||
}
|
|
||||||
wl_list_for_each(wlrSubsurface, &pSurface->current.subsurfaces_above, current.link) {
|
|
||||||
Events::listener_newSubsurfaceNode(PNODE, wlrSubsurface);
|
|
||||||
}
|
|
||||||
|
|
||||||
return PNODE;
|
|
||||||
}
|
|
||||||
|
|
||||||
SSurfaceTreeNode* createSubsurfaceNode(SSurfaceTreeNode* pParent, SSubsurface* pSubsurface, wlr_surface* surface, CWindow* pWindow) {
|
|
||||||
const auto PNODE = createTree(surface, pWindow);
|
|
||||||
PNODE->pParent = pParent;
|
|
||||||
PNODE->pSubsurface = pSubsurface;
|
|
||||||
|
|
||||||
Debug::log(LOG, "Creating a subsurface Node! {}", pWindow);
|
|
||||||
|
|
||||||
return PNODE;
|
|
||||||
}
|
|
||||||
|
|
||||||
SSurfaceTreeNode* SubsurfaceTree::createTreeRoot(wlr_surface* pSurface, applyGlobalOffsetFn fn, void* data, CWindow* pWindow) {
|
|
||||||
const auto PNODE = createTree(pSurface, pWindow);
|
|
||||||
|
|
||||||
Debug::log(LOG, "Creating a surfaceTree Root! {}", pWindow);
|
|
||||||
|
|
||||||
PNODE->offsetfn = fn;
|
|
||||||
PNODE->globalOffsetData = data;
|
|
||||||
|
|
||||||
return PNODE;
|
|
||||||
}
|
|
||||||
|
|
||||||
void destroySubsurface(SSubsurface* pSubsurface);
|
|
||||||
|
|
||||||
void SubsurfaceTree::destroySurfaceTree(SSurfaceTreeNode* pNode) {
|
|
||||||
bool exists = false;
|
|
||||||
for (auto& n : surfaceTreeNodes) {
|
|
||||||
if (&n == pNode) {
|
|
||||||
exists = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!exists) {
|
|
||||||
Debug::log(ERR, "Tried to remove a SurfaceTreeNode that doesn't exist?? (Node {:x})", (uintptr_t)pNode);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto& c : pNode->childSubsurfaces)
|
|
||||||
destroySubsurface(&c);
|
|
||||||
|
|
||||||
pNode->childSubsurfaces.clear();
|
|
||||||
|
|
||||||
pNode->hyprListener_commit.removeCallback();
|
|
||||||
pNode->hyprListener_destroy.removeCallback();
|
|
||||||
pNode->hyprListener_newSubsurface.removeCallback();
|
|
||||||
|
|
||||||
// damage
|
|
||||||
if (pNode->pSurface && pNode->pSurface->exists()) {
|
|
||||||
CBox extents = {};
|
|
||||||
wlr_surface_get_extends(pNode->pSurface->wlr(), extents.pWlr());
|
|
||||||
extents.applyFromWlr();
|
|
||||||
|
|
||||||
int lx = 0, ly = 0;
|
|
||||||
addSurfaceGlobalOffset(pNode, &lx, &ly);
|
|
||||||
|
|
||||||
extents.x += lx;
|
|
||||||
extents.y += ly;
|
|
||||||
|
|
||||||
g_pHyprRenderer->damageBox(&extents);
|
|
||||||
}
|
|
||||||
|
|
||||||
// remove references to this node
|
|
||||||
for (auto& tn : surfaceTreeNodes) {
|
|
||||||
for (auto& cs : tn.childSubsurfaces) {
|
|
||||||
if (cs.pChild == pNode)
|
|
||||||
cs.pChild = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
surfaceTreeNodes.remove(*pNode);
|
|
||||||
|
|
||||||
Debug::log(LOG, "SurfaceTree Node removed");
|
|
||||||
}
|
|
||||||
|
|
||||||
void destroySubsurface(SSubsurface* pSubsurface) {
|
|
||||||
if (pSubsurface->pChild) {
|
|
||||||
SubsurfaceTree::destroySurfaceTree(pSubsurface->pChild);
|
|
||||||
pSubsurface->pChild = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
pSubsurface->hyprListener_destroy.removeCallback();
|
|
||||||
pSubsurface->hyprListener_map.removeCallback();
|
|
||||||
pSubsurface->hyprListener_unmap.removeCallback();
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Subsurface listeners
|
|
||||||
//
|
|
||||||
|
|
||||||
void Events::listener_newSubsurfaceNode(void* owner, void* data) {
|
|
||||||
SSurfaceTreeNode* pNode = (SSurfaceTreeNode*)owner;
|
|
||||||
|
|
||||||
const auto PSUBSURFACE = (wlr_subsurface*)data;
|
|
||||||
|
|
||||||
const auto PNEWSUBSURFACE = &pNode->childSubsurfaces.emplace_back();
|
|
||||||
|
|
||||||
Debug::log(LOG, "Added a new subsurface {:x}", (uintptr_t)PSUBSURFACE);
|
|
||||||
|
|
||||||
PNEWSUBSURFACE->pSubsurface = PSUBSURFACE;
|
|
||||||
PNEWSUBSURFACE->pParent = pNode;
|
|
||||||
|
|
||||||
PNEWSUBSURFACE->hyprListener_map.initCallback(&PSUBSURFACE->surface->events.map, &Events::listener_mapSubsurface, PNEWSUBSURFACE, "Subsurface");
|
|
||||||
PNEWSUBSURFACE->hyprListener_unmap.initCallback(&PSUBSURFACE->surface->events.unmap, &Events::listener_unmapSubsurface, PNEWSUBSURFACE, "Subsurface");
|
|
||||||
PNEWSUBSURFACE->hyprListener_destroy.initCallback(&PSUBSURFACE->events.destroy, &Events::listener_destroySubsurface, PNEWSUBSURFACE, "Subsurface");
|
|
||||||
|
|
||||||
PNEWSUBSURFACE->pWindowOwner = pNode->pWindowOwner;
|
|
||||||
|
|
||||||
if (PSUBSURFACE->surface->mapped)
|
|
||||||
listener_mapSubsurface(PNEWSUBSURFACE, nullptr);
|
|
||||||
|
|
||||||
wlr_subsurface* existingWlrSubsurface;
|
|
||||||
wl_list_for_each(existingWlrSubsurface, &PSUBSURFACE->surface->current.subsurfaces_below, current.link) {
|
|
||||||
listener_newSubsurfaceNode(pNode, existingWlrSubsurface);
|
|
||||||
}
|
|
||||||
wl_list_for_each(existingWlrSubsurface, &PSUBSURFACE->surface->current.subsurfaces_above, current.link) {
|
|
||||||
listener_newSubsurfaceNode(pNode, existingWlrSubsurface);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Events::listener_mapSubsurface(void* owner, void* data) {
|
|
||||||
SSubsurface* subsurface = (SSubsurface*)owner;
|
|
||||||
|
|
||||||
if (subsurface->pChild)
|
|
||||||
return;
|
|
||||||
|
|
||||||
Debug::log(LOG, "Subsurface {:x} mapped", (uintptr_t)subsurface->pSubsurface);
|
|
||||||
|
|
||||||
subsurface->pChild = createSubsurfaceNode(subsurface->pParent, subsurface, subsurface->pSubsurface->surface, subsurface->pWindowOwner);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Events::listener_unmapSubsurface(void* owner, void* data) {
|
|
||||||
SSubsurface* subsurface = (SSubsurface*)owner;
|
|
||||||
|
|
||||||
Debug::log(LOG, "Subsurface {:x} unmapped", (uintptr_t)subsurface);
|
|
||||||
|
|
||||||
if (subsurface->pSubsurface->surface == g_pCompositor->m_pLastFocus)
|
|
||||||
g_pInputManager->releaseAllMouseButtons();
|
|
||||||
|
|
||||||
if (subsurface->pChild) {
|
|
||||||
const auto PNODE = subsurface->pChild;
|
|
||||||
|
|
||||||
const auto IT =
|
|
||||||
std::find_if(SubsurfaceTree::surfaceTreeNodes.begin(), SubsurfaceTree::surfaceTreeNodes.end(), [&](const SSurfaceTreeNode& other) { return &other == PNODE; });
|
|
||||||
|
|
||||||
if (IT != SubsurfaceTree::surfaceTreeNodes.end()) {
|
|
||||||
if (PNODE->pSurface && PNODE->pSurface->exists()) {
|
|
||||||
int lx = 0, ly = 0;
|
|
||||||
addSurfaceGlobalOffset(PNODE, &lx, &ly);
|
|
||||||
|
|
||||||
CBox extents = {lx, ly, 0, 0};
|
|
||||||
|
|
||||||
extents.width = PNODE->pSurface->wlr()->current.width;
|
|
||||||
extents.height = PNODE->pSurface->wlr()->current.height;
|
|
||||||
|
|
||||||
g_pHyprRenderer->damageBox(&extents);
|
|
||||||
}
|
|
||||||
|
|
||||||
// SubsurfaceTree::destroySurfaceTree(subsurface->pChild);
|
|
||||||
// subsurface->pChild = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
g_pInputManager->simulateMouseMovement(); // to focus and return back to an appropriate surface
|
|
||||||
}
|
|
||||||
|
|
||||||
void Events::listener_commitSubsurface(void* owner, void* data) {
|
|
||||||
SSurfaceTreeNode* pNode = (SSurfaceTreeNode*)owner;
|
|
||||||
|
|
||||||
// no damaging if it's not visible
|
|
||||||
if (!g_pHyprRenderer->shouldRenderWindow(pNode->pWindowOwner)) {
|
|
||||||
pNode->lastSize = pNode->pSurface->exists() ? Vector2D{pNode->pSurface->wlr()->current.width, pNode->pSurface->wlr()->current.height} : Vector2D{};
|
|
||||||
|
|
||||||
static auto* const PLOGDAMAGE = &g_pConfigManager->getConfigValuePtr("debug:log_damage")->intValue;
|
|
||||||
if (*PLOGDAMAGE)
|
|
||||||
Debug::log(LOG, "Refusing to commit damage from {} because it's invisible.", pNode->pWindowOwner);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int lx = 0, ly = 0;
|
|
||||||
|
|
||||||
addSurfaceGlobalOffset(pNode, &lx, &ly);
|
|
||||||
|
|
||||||
const double SCALE = pNode->pWindowOwner && pNode->pWindowOwner->m_bIsX11 ? 1.0 / pNode->pWindowOwner->m_fX11SurfaceScaledBy : 1.0;
|
|
||||||
|
|
||||||
// I do not think this is correct, but it solves a lot of issues with some apps (e.g. firefox)
|
|
||||||
// What this does is that basically, if the pNode is a child of some other node, on commit,
|
|
||||||
// it will also damage (check & damage if needed) all its siblings.
|
|
||||||
if (pNode->pParent)
|
|
||||||
for (auto& cs : pNode->pParent->childSubsurfaces) {
|
|
||||||
const auto NODECOORDS = pNode->pSubsurface ? Vector2D(pNode->pSubsurface->pSubsurface->current.x, pNode->pSubsurface->pSubsurface->current.y) : Vector2D();
|
|
||||||
|
|
||||||
if (&cs != pNode->pSubsurface && cs.pSubsurface) {
|
|
||||||
g_pHyprRenderer->damageSurface(cs.pSubsurface->surface, lx - NODECOORDS.x + cs.pSubsurface->current.x, ly - NODECOORDS.y + cs.pSubsurface->current.y, SCALE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pNode->pSurface && pNode->pSurface->exists()) {
|
|
||||||
g_pHyprRenderer->damageSurface(pNode->pSurface->wlr(), lx, ly, SCALE);
|
|
||||||
|
|
||||||
if (pNode->lastSize != Vector2D{pNode->pSurface->wlr()->current.width, pNode->pSurface->wlr()->current.height} && pNode->pWindowOwner)
|
|
||||||
g_pHyprRenderer->damageWindow(pNode->pWindowOwner);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pNode->pWindowOwner) {
|
|
||||||
if (pNode->pWindowOwner->m_bIsX11)
|
|
||||||
pNode->pWindowOwner->m_vReportedSize = pNode->pWindowOwner->m_vPendingReportedSize; // apply pending size. We pinged, the window ponged.
|
|
||||||
|
|
||||||
// tearing: if solitary, redraw it. This still might be a single surface window
|
|
||||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(pNode->pWindowOwner->m_iMonitorID);
|
|
||||||
if (PMONITOR->solitaryClient == pNode->pWindowOwner && pNode->pWindowOwner->canBeTorn() && PMONITOR->tearingState.canTear &&
|
|
||||||
pNode->pSurface->wlr()->current.committed & WLR_SURFACE_STATE_BUFFER) {
|
|
||||||
CRegion damageBox;
|
|
||||||
wlr_surface_get_effective_damage(pNode->pSurface->wlr(), damageBox.pixman());
|
|
||||||
|
|
||||||
if (!damageBox.empty()) {
|
|
||||||
|
|
||||||
if (PMONITOR->tearingState.busy) {
|
|
||||||
PMONITOR->tearingState.frameScheduledWhileBusy = true;
|
|
||||||
} else {
|
|
||||||
PMONITOR->tearingState.nextRenderTorn = true;
|
|
||||||
g_pHyprRenderer->renderMonitor(PMONITOR);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pNode->lastSize = pNode->pSurface->exists() ? Vector2D{pNode->pSurface->wlr()->current.width, pNode->pSurface->wlr()->current.height} : Vector2D{};
|
|
||||||
}
|
|
||||||
|
|
||||||
void Events::listener_destroySubsurface(void* owner, void* data) {
|
|
||||||
SSubsurface* subsurface = (SSubsurface*)owner;
|
|
||||||
|
|
||||||
if (subsurface->pChild) {
|
|
||||||
SubsurfaceTree::destroySurfaceTree(subsurface->pChild);
|
|
||||||
}
|
|
||||||
|
|
||||||
Debug::log(LOG, "Subsurface {:x} destroyed", (uintptr_t)subsurface);
|
|
||||||
|
|
||||||
subsurface->hyprListener_destroy.removeCallback();
|
|
||||||
subsurface->hyprListener_map.removeCallback();
|
|
||||||
subsurface->hyprListener_unmap.removeCallback();
|
|
||||||
|
|
||||||
subsurface->pParent->childSubsurfaces.remove(*subsurface);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Events::listener_destroySubsurfaceNode(void* owner, void* data) {
|
|
||||||
SSurfaceTreeNode* pNode = (SSurfaceTreeNode*)owner;
|
|
||||||
|
|
||||||
Debug::log(LOG, "Subsurface Node {:x} destroyed", (uintptr_t)pNode);
|
|
||||||
|
|
||||||
for (auto& c : pNode->childSubsurfaces)
|
|
||||||
destroySubsurface(&c);
|
|
||||||
|
|
||||||
pNode->hyprListener_commit.removeCallback();
|
|
||||||
pNode->hyprListener_newSubsurface.removeCallback();
|
|
||||||
pNode->hyprListener_destroy.removeCallback();
|
|
||||||
|
|
||||||
SubsurfaceTree::surfaceTreeNodes.remove(*pNode);
|
|
||||||
}
|
|
|
@ -1,60 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "../defines.hpp"
|
|
||||||
#include <list>
|
|
||||||
#include "WLSurface.hpp"
|
|
||||||
|
|
||||||
struct SSubsurface;
|
|
||||||
class CWindow;
|
|
||||||
|
|
||||||
typedef void (*applyGlobalOffsetFn)(void*, int*, int*);
|
|
||||||
|
|
||||||
struct SSurfaceTreeNode {
|
|
||||||
CWLSurface* pSurface = nullptr; // actual surface
|
|
||||||
CWLSurface pInternalSurface; // not present for head nodes to not dupe wlr_surface ownership
|
|
||||||
|
|
||||||
DYNLISTENER(newSubsurface);
|
|
||||||
DYNLISTENER(commit);
|
|
||||||
DYNLISTENER(destroy);
|
|
||||||
|
|
||||||
SSurfaceTreeNode* pParent = nullptr;
|
|
||||||
SSubsurface* pSubsurface = nullptr;
|
|
||||||
|
|
||||||
std::list<SSubsurface> childSubsurfaces;
|
|
||||||
|
|
||||||
applyGlobalOffsetFn offsetfn;
|
|
||||||
void* globalOffsetData;
|
|
||||||
CWindow* pWindowOwner = nullptr;
|
|
||||||
|
|
||||||
Vector2D lastSize;
|
|
||||||
|
|
||||||
//
|
|
||||||
bool operator==(const SSurfaceTreeNode& rhs) const {
|
|
||||||
return pSurface == rhs.pSurface;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct SSubsurface {
|
|
||||||
wlr_subsurface* pSubsurface = nullptr;
|
|
||||||
|
|
||||||
SSurfaceTreeNode* pParent = nullptr;
|
|
||||||
SSurfaceTreeNode* pChild = nullptr;
|
|
||||||
|
|
||||||
DYNLISTENER(map);
|
|
||||||
DYNLISTENER(unmap);
|
|
||||||
DYNLISTENER(destroy);
|
|
||||||
|
|
||||||
CWindow* pWindowOwner = nullptr;
|
|
||||||
|
|
||||||
//
|
|
||||||
bool operator==(const SSubsurface& rhs) const {
|
|
||||||
return pSubsurface == rhs.pSubsurface;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace SubsurfaceTree {
|
|
||||||
SSurfaceTreeNode* createTreeRoot(wlr_surface*, applyGlobalOffsetFn, void*, CWindow* pWindow = nullptr);
|
|
||||||
void destroySurfaceTree(SSurfaceTreeNode*);
|
|
||||||
|
|
||||||
inline std::list<SSurfaceTreeNode> surfaceTreeNodes;
|
|
||||||
};
|
|
|
@ -12,6 +12,11 @@ Vector2D::Vector2D() {
|
||||||
y = 0;
|
y = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Vector2D::Vector2D(const Hyprlang::VEC2& ref) {
|
||||||
|
x = ref.x;
|
||||||
|
y = ref.y;
|
||||||
|
}
|
||||||
|
|
||||||
Vector2D::~Vector2D() {}
|
Vector2D::~Vector2D() {}
|
||||||
|
|
||||||
double Vector2D::normalize() {
|
double Vector2D::normalize() {
|
||||||
|
@ -42,14 +47,10 @@ double Vector2D::distance(const Vector2D& other) const {
|
||||||
return std::sqrt(dx * dx + dy * dy);
|
return std::sqrt(dx * dx + dy * dy);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Vector2D::inTriangle(const Vector2D& p1, const Vector2D& p2, const Vector2D& p3) const {
|
|
||||||
const auto a = ((p2.y - p3.y) * (x - p3.x) + (p3.x - p2.x) * (y - p3.y)) / ((p2.y - p3.y) * (p1.x - p3.x) + (p3.x - p2.x) * (p1.y - p3.y));
|
|
||||||
const auto b = ((p3.y - p1.y) * (x - p3.x) + (p1.x - p3.x) * (y - p3.y)) / ((p2.y - p3.y) * (p1.x - p3.x) + (p3.x - p2.x) * (p1.y - p3.y));
|
|
||||||
const auto c = 1 - a - b;
|
|
||||||
|
|
||||||
return 0 <= a && a <= 1 && 0 <= b && b <= 1 && 0 <= c && c <= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
double Vector2D::size() const {
|
double Vector2D::size() const {
|
||||||
return std::sqrt(x * x + y * y);
|
return std::sqrt(x * x + y * y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Vector2D Vector2D::getComponentMax(const Vector2D& other) const {
|
||||||
|
return Vector2D(std::max(this->x, other.x), std::max(this->y, other.y));
|
||||||
|
}
|
||||||
|
|
|
@ -3,12 +3,14 @@
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <format>
|
#include <format>
|
||||||
#include "../macros.hpp"
|
#include "../macros.hpp"
|
||||||
|
#include <hyprlang.hpp>
|
||||||
|
|
||||||
class Vector2D {
|
class Vector2D {
|
||||||
public:
|
public:
|
||||||
Vector2D(double, double);
|
Vector2D(double, double);
|
||||||
Vector2D();
|
Vector2D();
|
||||||
~Vector2D();
|
~Vector2D();
|
||||||
|
Vector2D(const Hyprlang::VEC2&);
|
||||||
|
|
||||||
double x = 0;
|
double x = 0;
|
||||||
double y = 0;
|
double y = 0;
|
||||||
|
@ -88,12 +90,12 @@ class Vector2D {
|
||||||
|
|
||||||
double distance(const Vector2D& other) const;
|
double distance(const Vector2D& other) const;
|
||||||
double size() const;
|
double size() const;
|
||||||
Vector2D clamp(const Vector2D& min, const Vector2D& max = Vector2D()) const;
|
Vector2D clamp(const Vector2D& min, const Vector2D& max = Vector2D{-1, -1}) const;
|
||||||
|
|
||||||
Vector2D floor() const;
|
Vector2D floor() const;
|
||||||
Vector2D round() const;
|
Vector2D round() const;
|
||||||
|
|
||||||
bool inTriangle(const Vector2D& p1, const Vector2D& p2, const Vector2D& p3) const;
|
Vector2D getComponentMax(const Vector2D& other) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -3,9 +3,17 @@
|
||||||
#include "../Compositor.hpp"
|
#include "../Compositor.hpp"
|
||||||
|
|
||||||
SLayerSurface::SLayerSurface() {
|
SLayerSurface::SLayerSurface() {
|
||||||
alpha.create(AVARTYPE_FLOAT, g_pConfigManager->getAnimationPropertyConfig("fadeIn"), nullptr, AVARDAMAGE_ENTIRE);
|
alpha.create(g_pConfigManager->getAnimationPropertyConfig("fadeLayers"), nullptr, AVARDAMAGE_ENTIRE);
|
||||||
alpha.m_pLayer = this;
|
realPosition.create(g_pConfigManager->getAnimationPropertyConfig("layers"), nullptr, AVARDAMAGE_ENTIRE);
|
||||||
|
realSize.create(g_pConfigManager->getAnimationPropertyConfig("layers"), nullptr, AVARDAMAGE_ENTIRE);
|
||||||
|
alpha.m_pLayer = this;
|
||||||
|
realPosition.m_pLayer = this;
|
||||||
|
realSize.m_pLayer = this;
|
||||||
alpha.registerVar();
|
alpha.registerVar();
|
||||||
|
realPosition.registerVar();
|
||||||
|
realSize.registerVar();
|
||||||
|
|
||||||
|
alpha.setValueAndWarp(0.f);
|
||||||
}
|
}
|
||||||
|
|
||||||
SLayerSurface::~SLayerSurface() {
|
SLayerSurface::~SLayerSurface() {
|
||||||
|
@ -22,6 +30,7 @@ void SLayerSurface::applyRules() {
|
||||||
ignoreAlpha = false;
|
ignoreAlpha = false;
|
||||||
ignoreAlphaValue = 0.f;
|
ignoreAlphaValue = 0.f;
|
||||||
xray = -1;
|
xray = -1;
|
||||||
|
animationStyle.reset();
|
||||||
|
|
||||||
for (auto& rule : g_pConfigManager->getMatchingRules(this)) {
|
for (auto& rule : g_pConfigManager->getMatchingRules(this)) {
|
||||||
if (rule.rule == "noanim")
|
if (rule.rule == "noanim")
|
||||||
|
@ -44,10 +53,120 @@ void SLayerSurface::applyRules() {
|
||||||
try {
|
try {
|
||||||
xray = configStringToInt(vars[1]);
|
xray = configStringToInt(vars[1]);
|
||||||
} catch (...) {}
|
} catch (...) {}
|
||||||
|
} else if (rule.rule.starts_with("animation")) {
|
||||||
|
CVarList vars{rule.rule, 2, 's'};
|
||||||
|
animationStyle = vars[1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SLayerSurface::startAnimation(bool in, bool instant) {
|
||||||
|
const auto ANIMSTYLE = animationStyle.value_or(realPosition.m_pConfig->pValues->internalStyle);
|
||||||
|
|
||||||
|
if (ANIMSTYLE == "slide") {
|
||||||
|
// get closest edge
|
||||||
|
const auto MIDDLE = geometry.middle();
|
||||||
|
|
||||||
|
const auto PMONITOR = g_pCompositor->getMonitorFromVector(MIDDLE);
|
||||||
|
|
||||||
|
const std::array<Vector2D, 4> edgePoints = {
|
||||||
|
PMONITOR->vecPosition + Vector2D{PMONITOR->vecSize.x / 2, 0},
|
||||||
|
PMONITOR->vecPosition + Vector2D{PMONITOR->vecSize.x / 2, PMONITOR->vecSize.y},
|
||||||
|
PMONITOR->vecPosition + Vector2D{0, PMONITOR->vecSize.y},
|
||||||
|
PMONITOR->vecPosition + Vector2D{PMONITOR->vecSize.x, PMONITOR->vecSize.y / 2},
|
||||||
|
};
|
||||||
|
|
||||||
|
float closest = std::numeric_limits<float>::max();
|
||||||
|
size_t leader = 0;
|
||||||
|
for (size_t i = 0; i < 4; ++i) {
|
||||||
|
float dist = MIDDLE.distance(edgePoints[i]);
|
||||||
|
if (dist < closest) {
|
||||||
|
leader = i;
|
||||||
|
closest = dist;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
realSize.setValueAndWarp(geometry.size());
|
||||||
|
alpha.setValueAndWarp(1.f);
|
||||||
|
|
||||||
|
Vector2D prePos;
|
||||||
|
|
||||||
|
switch (leader) {
|
||||||
|
case 0:
|
||||||
|
// TOP
|
||||||
|
prePos = {geometry.x, PMONITOR->vecPosition.y - geometry.h};
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
// BOTTOM
|
||||||
|
prePos = {geometry.x, PMONITOR->vecPosition.y + PMONITOR->vecPosition.y};
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
// LEFT
|
||||||
|
prePos = {PMONITOR->vecPosition.x - geometry.w, geometry.y};
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
// RIGHT
|
||||||
|
prePos = {PMONITOR->vecPosition.x + PMONITOR->vecSize.x, geometry.y};
|
||||||
|
break;
|
||||||
|
default: UNREACHABLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (in) {
|
||||||
|
realPosition.setValueAndWarp(prePos);
|
||||||
|
realPosition = geometry.pos();
|
||||||
|
} else {
|
||||||
|
realPosition.setValueAndWarp(geometry.pos());
|
||||||
|
realPosition = prePos;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (ANIMSTYLE.starts_with("popin")) {
|
||||||
|
float minPerc = 0.f;
|
||||||
|
if (ANIMSTYLE.find("%") != std::string::npos) {
|
||||||
|
try {
|
||||||
|
auto percstr = ANIMSTYLE.substr(ANIMSTYLE.find_last_of(' '));
|
||||||
|
minPerc = std::stoi(percstr.substr(0, percstr.length() - 1));
|
||||||
|
} catch (std::exception& e) {
|
||||||
|
; // oops
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
minPerc *= 0.01;
|
||||||
|
|
||||||
|
const auto GOALSIZE = (geometry.size() * minPerc).clamp({5, 5});
|
||||||
|
const auto GOALPOS = geometry.pos() + (geometry.size() - GOALSIZE) / 2.f;
|
||||||
|
|
||||||
|
alpha.setValueAndWarp(in ? 0.f : 1.f);
|
||||||
|
alpha = in ? 1.f : 0.f;
|
||||||
|
|
||||||
|
if (in) {
|
||||||
|
realSize.setValueAndWarp(GOALSIZE);
|
||||||
|
realPosition.setValueAndWarp(GOALPOS);
|
||||||
|
realSize = geometry.size();
|
||||||
|
realPosition = geometry.pos();
|
||||||
|
} else {
|
||||||
|
realSize.setValueAndWarp(geometry.size());
|
||||||
|
realPosition.setValueAndWarp(geometry.pos());
|
||||||
|
realSize = GOALSIZE;
|
||||||
|
realPosition = GOALPOS;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// fade
|
||||||
|
realPosition.setValueAndWarp(geometry.pos());
|
||||||
|
realSize.setValueAndWarp(geometry.size());
|
||||||
|
alpha = in ? 1.f : 0.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!in)
|
||||||
|
fadingOut = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SLayerSurface::isFadedOut() {
|
||||||
|
if (!fadingOut)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return !realPosition.isBeingAnimated() && !realSize.isBeingAnimated() && !alpha.isBeingAnimated();
|
||||||
|
}
|
||||||
|
|
||||||
CRegion SConstraint::getLogicCoordsRegion() {
|
CRegion SConstraint::getLogicCoordsRegion() {
|
||||||
CRegion result;
|
CRegion result;
|
||||||
|
|
||||||
|
@ -62,11 +181,11 @@ CRegion SConstraint::getLogicCoordsRegion() {
|
||||||
result.add(&constraint->region); // surface-local coords
|
result.add(&constraint->region); // surface-local coords
|
||||||
|
|
||||||
if (!PWINDOWOWNER->m_bIsX11) {
|
if (!PWINDOWOWNER->m_bIsX11) {
|
||||||
result.translate(PWINDOWOWNER->m_vRealPosition.goalv());
|
result.translate(PWINDOWOWNER->m_vRealPosition.goal());
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto COORDS = PWINDOWOWNER->m_bIsMapped ? PWINDOWOWNER->m_vRealPosition.goalv() :
|
const auto COORDS = PWINDOWOWNER->m_bIsMapped ? PWINDOWOWNER->m_vRealPosition.goal() :
|
||||||
g_pXWaylandManager->xwaylandToWaylandCoords({PWINDOWOWNER->m_uSurface.xwayland->x, PWINDOWOWNER->m_uSurface.xwayland->y});
|
g_pXWaylandManager->xwaylandToWaylandCoords({PWINDOWOWNER->m_uSurface.xwayland->x, PWINDOWOWNER->m_uSurface.xwayland->y});
|
||||||
|
|
||||||
const auto PMONITOR = PWINDOWOWNER->m_bIsMapped ? g_pCompositor->getMonitorFromID(PWINDOWOWNER->m_iMonitorID) : g_pCompositor->getMonitorFromVector(COORDS);
|
const auto PMONITOR = PWINDOWOWNER->m_bIsMapped ? g_pCompositor->getMonitorFromID(PWINDOWOWNER->m_iMonitorID) : g_pCompositor->getMonitorFromVector(COORDS);
|
||||||
|
@ -91,9 +210,9 @@ Vector2D SConstraint::getLogicConstraintPos() {
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
if (!PWINDOWOWNER->m_bIsX11)
|
if (!PWINDOWOWNER->m_bIsX11)
|
||||||
return PWINDOWOWNER->m_vRealPosition.goalv();
|
return PWINDOWOWNER->m_vRealPosition.goal();
|
||||||
|
|
||||||
const auto COORDS = PWINDOWOWNER->m_bIsMapped ? PWINDOWOWNER->m_vRealPosition.goalv() :
|
const auto COORDS = PWINDOWOWNER->m_bIsMapped ? PWINDOWOWNER->m_vRealPosition.goal() :
|
||||||
g_pXWaylandManager->xwaylandToWaylandCoords({PWINDOWOWNER->m_uSurface.xwayland->x, PWINDOWOWNER->m_uSurface.xwayland->y});
|
g_pXWaylandManager->xwaylandToWaylandCoords({PWINDOWOWNER->m_uSurface.xwayland->x, PWINDOWOWNER->m_uSurface.xwayland->y});
|
||||||
|
|
||||||
return COORDS;
|
return COORDS;
|
||||||
|
@ -109,7 +228,7 @@ Vector2D SConstraint::getLogicConstraintSize() {
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
if (!PWINDOWOWNER->m_bIsX11)
|
if (!PWINDOWOWNER->m_bIsX11)
|
||||||
return PWINDOWOWNER->m_vRealSize.goalv();
|
return PWINDOWOWNER->m_vRealSize.goal();
|
||||||
|
|
||||||
const auto PMONITOR = PWINDOWOWNER->m_bIsMapped ?
|
const auto PMONITOR = PWINDOWOWNER->m_bIsMapped ?
|
||||||
g_pCompositor->getMonitorFromID(PWINDOWOWNER->m_iMonitorID) :
|
g_pCompositor->getMonitorFromID(PWINDOWOWNER->m_iMonitorID) :
|
||||||
|
@ -118,8 +237,72 @@ Vector2D SConstraint::getLogicConstraintSize() {
|
||||||
if (!PMONITOR)
|
if (!PMONITOR)
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
const auto SIZE = PWINDOWOWNER->m_bIsMapped ? PWINDOWOWNER->m_vRealSize.goalv() :
|
const auto SIZE = PWINDOWOWNER->m_bIsMapped ? PWINDOWOWNER->m_vRealSize.goal() :
|
||||||
Vector2D{PWINDOWOWNER->m_uSurface.xwayland->width, PWINDOWOWNER->m_uSurface.xwayland->height} * PMONITOR->xwaylandScale;
|
Vector2D{PWINDOWOWNER->m_uSurface.xwayland->width, PWINDOWOWNER->m_uSurface.xwayland->height} * PMONITOR->xwaylandScale;
|
||||||
|
|
||||||
return SIZE;
|
return SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SKeyboard::updateXKBTranslationState(xkb_keymap* const keymap) {
|
||||||
|
xkb_state_unref(xkbTranslationState);
|
||||||
|
|
||||||
|
if (keymap) {
|
||||||
|
Debug::log(LOG, "Updating keyboard {:x}'s translation state from a provided keymap", (uintptr_t)this);
|
||||||
|
xkbTranslationState = xkb_state_new(keymap);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto WLRKB = wlr_keyboard_from_input_device(keyboard);
|
||||||
|
const auto KEYMAP = WLRKB->keymap;
|
||||||
|
const auto STATE = WLRKB->xkb_state;
|
||||||
|
const auto LAYOUTSNUM = xkb_keymap_num_layouts(KEYMAP);
|
||||||
|
|
||||||
|
const auto PCONTEXT = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < LAYOUTSNUM; ++i) {
|
||||||
|
if (xkb_state_layout_index_is_active(STATE, i, XKB_STATE_LAYOUT_EFFECTIVE)) {
|
||||||
|
Debug::log(LOG, "Updating keyboard {:x}'s translation state from an active index {}", (uintptr_t)this, i);
|
||||||
|
|
||||||
|
CVarList keyboardLayouts(currentRules.layout, 0, ',');
|
||||||
|
CVarList keyboardModels(currentRules.model, 0, ',');
|
||||||
|
CVarList keyboardVariants(currentRules.variant, 0, ',');
|
||||||
|
|
||||||
|
xkb_rule_names rules = {.rules = "", .model = "", .layout = "", .variant = "", .options = ""};
|
||||||
|
|
||||||
|
std::string layout, model, variant;
|
||||||
|
layout = keyboardLayouts[i % keyboardLayouts.size()];
|
||||||
|
model = keyboardModels[i % keyboardLayouts.size()];
|
||||||
|
variant = keyboardVariants[i % keyboardLayouts.size()];
|
||||||
|
|
||||||
|
rules.layout = layout.c_str();
|
||||||
|
rules.model = model.c_str();
|
||||||
|
rules.variant = variant.c_str();
|
||||||
|
|
||||||
|
const auto KEYMAP = xkb_keymap_new_from_names(PCONTEXT, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS);
|
||||||
|
|
||||||
|
xkbTranslationState = xkb_state_new(KEYMAP);
|
||||||
|
|
||||||
|
xkb_keymap_unref(KEYMAP);
|
||||||
|
xkb_context_unref(PCONTEXT);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Debug::log(LOG, "Updating keyboard {:x}'s translation state from an unknown index", (uintptr_t)this);
|
||||||
|
|
||||||
|
xkb_rule_names rules = {
|
||||||
|
.rules = currentRules.rules.c_str(),
|
||||||
|
.model = currentRules.model.c_str(),
|
||||||
|
.layout = currentRules.layout.c_str(),
|
||||||
|
.variant = currentRules.variant.c_str(),
|
||||||
|
.options = currentRules.options.c_str(),
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto NEWKEYMAP = xkb_keymap_new_from_names(PCONTEXT, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS);
|
||||||
|
|
||||||
|
xkbTranslationState = xkb_state_new(NEWKEYMAP);
|
||||||
|
|
||||||
|
xkb_keymap_unref(NEWKEYMAP);
|
||||||
|
xkb_context_unref(PCONTEXT);
|
||||||
|
}
|
||||||
|
|
|
@ -4,9 +4,10 @@
|
||||||
#include "../defines.hpp"
|
#include "../defines.hpp"
|
||||||
#include "wlr-layer-shell-unstable-v1-protocol.h"
|
#include "wlr-layer-shell-unstable-v1-protocol.h"
|
||||||
#include "../Window.hpp"
|
#include "../Window.hpp"
|
||||||
#include "SubsurfaceTree.hpp"
|
#include "../desktop/Subsurface.hpp"
|
||||||
|
#include "../desktop/Popup.hpp"
|
||||||
#include "AnimatedVariable.hpp"
|
#include "AnimatedVariable.hpp"
|
||||||
#include "WLSurface.hpp"
|
#include "../desktop/WLSurface.hpp"
|
||||||
#include "Region.hpp"
|
#include "Region.hpp"
|
||||||
|
|
||||||
struct SLayerRule {
|
struct SLayerRule {
|
||||||
|
@ -18,42 +19,50 @@ struct SLayerSurface {
|
||||||
SLayerSurface();
|
SLayerSurface();
|
||||||
~SLayerSurface();
|
~SLayerSurface();
|
||||||
|
|
||||||
void applyRules();
|
void applyRules();
|
||||||
|
void startAnimation(bool in, bool instant = false);
|
||||||
|
bool isFadedOut();
|
||||||
|
|
||||||
wlr_layer_surface_v1* layerSurface;
|
CAnimatedVariable<Vector2D> realPosition;
|
||||||
wl_list link;
|
CAnimatedVariable<Vector2D> realSize;
|
||||||
|
|
||||||
bool keyboardExclusive = false;
|
wlr_layer_surface_v1* layerSurface;
|
||||||
|
wl_list link;
|
||||||
|
|
||||||
CWLSurface surface;
|
bool keyboardExclusive = false;
|
||||||
std::list<CWLSurface> popupSurfaces;
|
|
||||||
|
CWLSurface surface;
|
||||||
|
|
||||||
|
// desktop components
|
||||||
|
std::unique_ptr<CPopup> popupHead;
|
||||||
|
|
||||||
DYNLISTENER(destroyLayerSurface);
|
DYNLISTENER(destroyLayerSurface);
|
||||||
DYNLISTENER(mapLayerSurface);
|
DYNLISTENER(mapLayerSurface);
|
||||||
DYNLISTENER(unmapLayerSurface);
|
DYNLISTENER(unmapLayerSurface);
|
||||||
DYNLISTENER(commitLayerSurface);
|
DYNLISTENER(commitLayerSurface);
|
||||||
DYNLISTENER(newPopup);
|
|
||||||
|
|
||||||
CBox geometry = {0, 0, 0, 0};
|
CBox geometry = {0, 0, 0, 0};
|
||||||
Vector2D position;
|
Vector2D position;
|
||||||
zwlr_layer_shell_v1_layer layer;
|
zwlr_layer_shell_v1_layer layer;
|
||||||
|
|
||||||
bool mapped = false;
|
bool mapped = false;
|
||||||
|
|
||||||
int monitorID = -1;
|
int monitorID = -1;
|
||||||
|
|
||||||
std::string szNamespace = "";
|
std::string szNamespace = "";
|
||||||
|
|
||||||
CAnimatedVariable alpha;
|
CAnimatedVariable<float> alpha;
|
||||||
bool fadingOut = false;
|
bool fadingOut = false;
|
||||||
bool readyToDelete = false;
|
bool readyToDelete = false;
|
||||||
bool noProcess = false;
|
bool noProcess = false;
|
||||||
bool noAnimations = false;
|
bool noAnimations = false;
|
||||||
|
|
||||||
bool forceBlur = false;
|
bool forceBlur = false;
|
||||||
int xray = -1;
|
int xray = -1;
|
||||||
bool ignoreAlpha = false;
|
bool ignoreAlpha = false;
|
||||||
float ignoreAlphaValue = 0.f;
|
float ignoreAlphaValue = 0.f;
|
||||||
|
|
||||||
|
std::optional<std::string> animationStyle;
|
||||||
|
|
||||||
// For the list lookup
|
// For the list lookup
|
||||||
bool operator==(const SLayerSurface& rhs) const {
|
bool operator==(const SLayerSurface& rhs) const {
|
||||||
|
@ -127,15 +136,19 @@ struct SKeyboard {
|
||||||
bool active = false;
|
bool active = false;
|
||||||
bool enabled = true;
|
bool enabled = true;
|
||||||
|
|
||||||
xkb_layout_index_t activeLayout = 0;
|
xkb_layout_index_t activeLayout = 0;
|
||||||
|
xkb_state* xkbTranslationState = nullptr;
|
||||||
|
|
||||||
std::string name = "";
|
std::string name = "";
|
||||||
std::string xkbFilePath = "";
|
std::string xkbFilePath = "";
|
||||||
|
|
||||||
SStringRuleNames currentRules;
|
SStringRuleNames currentRules;
|
||||||
int repeatRate = 0;
|
int repeatRate = 0;
|
||||||
int repeatDelay = 0;
|
int repeatDelay = 0;
|
||||||
int numlockOn = -1;
|
int numlockOn = -1;
|
||||||
|
bool resolveBindsBySym = false;
|
||||||
|
|
||||||
|
void updateXKBTranslationState(xkb_keymap* const keymap = nullptr);
|
||||||
|
|
||||||
// For the list lookup
|
// For the list lookup
|
||||||
bool operator==(const SKeyboard& rhs) const {
|
bool operator==(const SKeyboard& rhs) const {
|
||||||
|
@ -190,34 +203,6 @@ struct SConstraint {
|
||||||
|
|
||||||
class CMonitor;
|
class CMonitor;
|
||||||
|
|
||||||
struct SXDGPopup {
|
|
||||||
CWindow* parentWindow = nullptr;
|
|
||||||
SLayerSurface* parentLS = nullptr;
|
|
||||||
SXDGPopup* parentPopup = nullptr;
|
|
||||||
wlr_xdg_popup* popup = nullptr;
|
|
||||||
CMonitor* monitor = nullptr;
|
|
||||||
|
|
||||||
DYNLISTENER(newPopupFromPopupXDG);
|
|
||||||
DYNLISTENER(destroyPopupXDG);
|
|
||||||
DYNLISTENER(mapPopupXDG);
|
|
||||||
DYNLISTENER(unmapPopupXDG);
|
|
||||||
DYNLISTENER(commitPopupXDG);
|
|
||||||
DYNLISTENER(repositionPopupXDG);
|
|
||||||
|
|
||||||
double lx;
|
|
||||||
double ly;
|
|
||||||
|
|
||||||
Vector2D lastPos = {};
|
|
||||||
bool repositionRequested = false;
|
|
||||||
|
|
||||||
SSurfaceTreeNode* pSurfaceTree = nullptr;
|
|
||||||
|
|
||||||
// For the list lookup
|
|
||||||
bool operator==(const SXDGPopup& rhs) const {
|
|
||||||
return popup == rhs.popup;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct SSeat {
|
struct SSeat {
|
||||||
wlr_seat* seat = nullptr;
|
wlr_seat* seat = nullptr;
|
||||||
wl_client* exclusiveClient = nullptr;
|
wl_client* exclusiveClient = nullptr;
|
||||||
|
@ -259,6 +244,8 @@ struct STablet {
|
||||||
|
|
||||||
std::string name = "";
|
std::string name = "";
|
||||||
|
|
||||||
|
std::string boundOutput = "";
|
||||||
|
|
||||||
//
|
//
|
||||||
bool operator==(const STablet& b) const {
|
bool operator==(const STablet& b) const {
|
||||||
return wlrDevice == b.wlrDevice;
|
return wlrDevice == b.wlrDevice;
|
||||||
|
@ -406,7 +393,17 @@ struct STearingController {
|
||||||
DYNLISTENER(set);
|
DYNLISTENER(set);
|
||||||
DYNLISTENER(destroy);
|
DYNLISTENER(destroy);
|
||||||
|
|
||||||
bool operator==(const STearingController& other) {
|
bool operator==(const STearingController& other) const {
|
||||||
return pWlrHint == other.pWlrHint;
|
return pWlrHint == other.pWlrHint;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct SShortcutInhibitor {
|
||||||
|
wlr_keyboard_shortcuts_inhibitor_v1* pWlrInhibitor = nullptr;
|
||||||
|
|
||||||
|
DYNLISTENER(destroy);
|
||||||
|
|
||||||
|
bool operator==(const SShortcutInhibitor& other) const {
|
||||||
|
return pWlrInhibitor == other.pWlrInhibitor;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
|
@ -7,13 +7,15 @@
|
||||||
void handleWrapped(wl_listener* listener, void* data) {
|
void handleWrapped(wl_listener* listener, void* data) {
|
||||||
CHyprWLListener::SWrapper* pWrap = wl_container_of(listener, pWrap, m_sListener);
|
CHyprWLListener::SWrapper* pWrap = wl_container_of(listener, pWrap, m_sListener);
|
||||||
|
|
||||||
g_pWatchdog->startWatching();
|
if (g_pWatchdog)
|
||||||
|
g_pWatchdog->startWatching();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
pWrap->m_pSelf->emit(data);
|
pWrap->m_pSelf->emit(data);
|
||||||
} catch (std::exception& e) { Debug::log(ERR, "Listener {} timed out and was killed by Watchdog!!!", (uintptr_t)listener); }
|
} catch (std::exception& e) { Debug::log(ERR, "Listener {} timed out and was killed by Watchdog!!!", (uintptr_t)listener); }
|
||||||
|
|
||||||
g_pWatchdog->endWatching();
|
if (g_pWatchdog)
|
||||||
|
g_pWatchdog->endWatching();
|
||||||
}
|
}
|
||||||
|
|
||||||
CHyprWLListener::CHyprWLListener(wl_signal* pSignal, std::function<void(void*, void*)> callback, void* pOwner) {
|
CHyprWLListener::CHyprWLListener(wl_signal* pSignal, std::function<void(void*, void*)> callback, void* pOwner) {
|
||||||
|
|
|
@ -1,87 +0,0 @@
|
||||||
#include "WLSurface.hpp"
|
|
||||||
#include "../Compositor.hpp"
|
|
||||||
|
|
||||||
CWLSurface::CWLSurface(wlr_surface* pSurface) {
|
|
||||||
m_pWLRSurface = pSurface;
|
|
||||||
init();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CWLSurface::assign(wlr_surface* pSurface) {
|
|
||||||
m_pWLRSurface = pSurface;
|
|
||||||
init();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CWLSurface::unassign() {
|
|
||||||
destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
CWLSurface::~CWLSurface() {
|
|
||||||
destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CWLSurface::exists() const {
|
|
||||||
return m_pWLRSurface;
|
|
||||||
}
|
|
||||||
|
|
||||||
wlr_surface* CWLSurface::wlr() const {
|
|
||||||
return m_pWLRSurface;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CWLSurface::small() const {
|
|
||||||
if (!m_pOwner || !exists())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return m_pOwner->m_vReportedSize.x > m_pWLRSurface->current.buffer_width + 1 || m_pOwner->m_vReportedSize.y > m_pWLRSurface->current.buffer_height + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector2D CWLSurface::correctSmallVec() const {
|
|
||||||
if (!m_pOwner || !exists() || !small() || m_bFillIgnoreSmall)
|
|
||||||
return {};
|
|
||||||
|
|
||||||
const auto SIZE = getViewporterCorrectedSize();
|
|
||||||
|
|
||||||
return Vector2D{(m_pOwner->m_vReportedSize.x - SIZE.x) / 2, (m_pOwner->m_vReportedSize.y - SIZE.y) / 2}.clamp({}, {INFINITY, INFINITY}) *
|
|
||||||
(m_pOwner->m_vRealSize.vec() / m_pOwner->m_vReportedSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector2D CWLSurface::getViewporterCorrectedSize() const {
|
|
||||||
if (!exists())
|
|
||||||
return {};
|
|
||||||
|
|
||||||
return m_pWLRSurface->current.viewport.has_dst ? Vector2D{m_pWLRSurface->current.viewport.dst_width, m_pWLRSurface->current.viewport.dst_height} :
|
|
||||||
Vector2D{m_pWLRSurface->current.buffer_width, m_pWLRSurface->current.buffer_height};
|
|
||||||
}
|
|
||||||
|
|
||||||
void CWLSurface::destroy() {
|
|
||||||
if (!m_pWLRSurface)
|
|
||||||
return;
|
|
||||||
|
|
||||||
hyprListener_destroy.removeCallback();
|
|
||||||
m_pWLRSurface->data = nullptr;
|
|
||||||
m_pOwner = nullptr;
|
|
||||||
|
|
||||||
if (g_pCompositor->m_pLastFocus == m_pWLRSurface)
|
|
||||||
g_pCompositor->m_pLastFocus = nullptr;
|
|
||||||
if (g_pInputManager->m_pLastMouseSurface == m_pWLRSurface)
|
|
||||||
g_pInputManager->m_pLastMouseSurface = nullptr;
|
|
||||||
if (g_pHyprRenderer->m_sLastCursorData.surf == m_pWLRSurface)
|
|
||||||
g_pHyprRenderer->m_sLastCursorData.surf.reset();
|
|
||||||
|
|
||||||
m_pWLRSurface = nullptr;
|
|
||||||
|
|
||||||
Debug::log(LOG, "CWLSurface {:x} called destroy()", (uintptr_t)this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CWLSurface::init() {
|
|
||||||
if (!m_pWLRSurface)
|
|
||||||
return;
|
|
||||||
|
|
||||||
RASSERT(!m_pWLRSurface->data, "Attempted to duplicate CWLSurface ownership!");
|
|
||||||
|
|
||||||
m_pWLRSurface->data = this;
|
|
||||||
|
|
||||||
hyprListener_destroy.initCallback(
|
|
||||||
&m_pWLRSurface->events.destroy, [&](void* owner, void* data) { destroy(); }, this, "CWLSurface");
|
|
||||||
|
|
||||||
Debug::log(LOG, "CWLSurface {:x} called init()", (uintptr_t)this);
|
|
||||||
}
|
|
|
@ -13,7 +13,7 @@ CWatchdog::CWatchdog() {
|
||||||
m_iMainThreadPID = pthread_self();
|
m_iMainThreadPID = pthread_self();
|
||||||
|
|
||||||
m_pWatchdog = std::make_unique<std::thread>([this] {
|
m_pWatchdog = std::make_unique<std::thread>([this] {
|
||||||
static auto* const PTIMEOUT = &g_pConfigManager->getConfigValuePtr("debug:watchdog_timeout")->intValue;
|
static auto* const PTIMEOUT = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("debug:watchdog_timeout");
|
||||||
|
|
||||||
while (1337) {
|
while (1337) {
|
||||||
std::unique_lock lk(m_mWatchdogMutex);
|
std::unique_lock lk(m_mWatchdogMutex);
|
||||||
|
@ -21,7 +21,7 @@ CWatchdog::CWatchdog() {
|
||||||
if (!m_bWillWatch)
|
if (!m_bWillWatch)
|
||||||
m_cvWatchdogCondition.wait(lk, [this] { return m_bNotified; });
|
m_cvWatchdogCondition.wait(lk, [this] { return m_bNotified; });
|
||||||
else {
|
else {
|
||||||
if (m_cvWatchdogCondition.wait_for(lk, std::chrono::milliseconds((int)(*PTIMEOUT * 1000.0)), [this] { return m_bNotified; }) == false)
|
if (m_cvWatchdogCondition.wait_for(lk, std::chrono::milliseconds((int)(**PTIMEOUT * 1000.0)), [this] { return m_bNotified; }) == false)
|
||||||
pthread_kill(m_iMainThreadPID, SIGUSR1);
|
pthread_kill(m_iMainThreadPID, SIGUSR1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,9 +37,9 @@ CWatchdog::CWatchdog() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void CWatchdog::startWatching() {
|
void CWatchdog::startWatching() {
|
||||||
static auto* const PTIMEOUT = &g_pConfigManager->getConfigValuePtr("debug:watchdog_timeout")->intValue;
|
static auto* const PTIMEOUT = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("debug:watchdog_timeout");
|
||||||
|
|
||||||
if (*PTIMEOUT == 0)
|
if (**PTIMEOUT == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
m_tTriggered = std::chrono::high_resolution_clock::now();
|
m_tTriggered = std::chrono::high_resolution_clock::now();
|
||||||
|
|
|
@ -139,7 +139,7 @@ void CHyprError::draw() {
|
||||||
|
|
||||||
if (m_bQueuedDestroy) {
|
if (m_bQueuedDestroy) {
|
||||||
if (!m_fFadeOpacity.isBeingAnimated()) {
|
if (!m_fFadeOpacity.isBeingAnimated()) {
|
||||||
if (m_fFadeOpacity.fl() == 0.f) {
|
if (m_fFadeOpacity.value() == 0.f) {
|
||||||
m_bQueuedDestroy = false;
|
m_bQueuedDestroy = false;
|
||||||
m_tTexture.destroyTexture();
|
m_tTexture.destroyTexture();
|
||||||
m_bIsCreated = false;
|
m_bIsCreated = false;
|
||||||
|
@ -164,7 +164,7 @@ void CHyprError::draw() {
|
||||||
|
|
||||||
m_bMonitorChanged = false;
|
m_bMonitorChanged = false;
|
||||||
|
|
||||||
g_pHyprOpenGL->renderTexture(m_tTexture, &monbox, m_fFadeOpacity.fl(), 0);
|
g_pHyprOpenGL->renderTexture(m_tTexture, &monbox, m_fFadeOpacity.value(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CHyprError::destroy() {
|
void CHyprError::destroy() {
|
||||||
|
|
|
@ -16,16 +16,16 @@ class CHyprError {
|
||||||
void destroy();
|
void destroy();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void createQueued();
|
void createQueued();
|
||||||
std::string m_szQueued = "";
|
std::string m_szQueued = "";
|
||||||
CColor m_cQueued;
|
CColor m_cQueued;
|
||||||
bool m_bQueuedDestroy = false;
|
bool m_bQueuedDestroy = false;
|
||||||
bool m_bIsCreated = false;
|
bool m_bIsCreated = false;
|
||||||
CTexture m_tTexture;
|
CTexture m_tTexture;
|
||||||
CAnimatedVariable m_fFadeOpacity;
|
CAnimatedVariable<float> m_fFadeOpacity;
|
||||||
CBox m_bDamageBox = {0, 0, 0, 0};
|
CBox m_bDamageBox = {0, 0, 0, 0};
|
||||||
|
|
||||||
bool m_bMonitorChanged = false;
|
bool m_bMonitorChanged = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline std::unique_ptr<CHyprError> g_pHyprError; // This is a full-screen error. Treat it with respect, and there can only be one at a time.
|
inline std::unique_ptr<CHyprError> g_pHyprError; // This is a full-screen error. Treat it with respect, and there can only be one at a time.
|
||||||
|
|
|
@ -4,13 +4,12 @@
|
||||||
|
|
||||||
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* const PSMARTSPLIT = &g_pConfigManager->getConfigValuePtr("dwindle:smart_split")->intValue;
|
static auto* const PSMARTSPLIT = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("dwindle:smart_split");
|
||||||
static auto* const PPRESERVESPLIT = &g_pConfigManager->getConfigValuePtr("dwindle:preserve_split")->intValue;
|
static auto* const PPRESERVESPLIT = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("dwindle:preserve_split");
|
||||||
static auto* const PFLMULT = &g_pConfigManager->getConfigValuePtr("dwindle:split_width_multiplier")->floatValue;
|
static auto* const PFLMULT = (Hyprlang::FLOAT* const*)g_pConfigManager->getConfigValuePtr("dwindle:split_width_multiplier");
|
||||||
|
|
||||||
if (*PPRESERVESPLIT == 0 && *PSMARTSPLIT == 0) {
|
if (**PPRESERVESPLIT == 0 && **PSMARTSPLIT == 0)
|
||||||
splitTop = box.h * *PFLMULT > box.w;
|
splitTop = box.h * **PFLMULT > box.w;
|
||||||
}
|
|
||||||
|
|
||||||
if (verticalOverride == true)
|
if (verticalOverride == true)
|
||||||
splitTop = true;
|
splitTop = true;
|
||||||
|
@ -22,13 +21,13 @@ void SDwindleNodeData::recalcSizePosRecursive(bool force, bool horizontalOverrid
|
||||||
if (SPLITSIDE) {
|
if (SPLITSIDE) {
|
||||||
// split left/right
|
// split left/right
|
||||||
const float FIRSTSIZE = box.w / 2.0 * splitRatio;
|
const float FIRSTSIZE = box.w / 2.0 * splitRatio;
|
||||||
children[0]->box = CBox{box.x, box.y, FIRSTSIZE, box.h};
|
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};
|
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 FIRSTSIZE = box.h / 2.0 * splitRatio;
|
const float FIRSTSIZE = box.h / 2.0 * splitRatio;
|
||||||
children[0]->box = CBox{box.x, box.y, box.w, FIRSTSIZE};
|
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};
|
children[1]->box = CBox{box.x, box.y + FIRSTSIZE, box.w, box.h - FIRSTSIZE}.noNegativeSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
children[0]->recalcSizePosRecursive(force);
|
children[0]->recalcSizePosRecursive(force);
|
||||||
|
@ -64,6 +63,21 @@ SDwindleNodeData* CHyprDwindleLayout::getFirstNodeOnWorkspace(const int& id) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SDwindleNodeData* CHyprDwindleLayout::getClosestNodeOnWorkspace(const int& id, const Vector2D& point) {
|
||||||
|
SDwindleNodeData* res = nullptr;
|
||||||
|
double distClosest = -1;
|
||||||
|
for (auto& n : m_lDwindleNodesData) {
|
||||||
|
if (n.workspaceID == id && n.pWindow && g_pCompositor->windowValidMapped(n.pWindow)) {
|
||||||
|
auto distAnother = vecToRectDistanceSquared(point, n.box.pos(), n.box.pos() + n.box.size());
|
||||||
|
if (!res || distAnother < distClosest) {
|
||||||
|
res = &n;
|
||||||
|
distClosest = distAnother;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
SDwindleNodeData* CHyprDwindleLayout::getNodeFromWindow(CWindow* pWindow) {
|
SDwindleNodeData* CHyprDwindleLayout::getNodeFromWindow(CWindow* pWindow) {
|
||||||
for (auto& n : m_lDwindleNodesData) {
|
for (auto& n : m_lDwindleNodesData) {
|
||||||
if (n.pWindow == pWindow && !n.isNode)
|
if (n.pWindow == pWindow && !n.isNode)
|
||||||
|
@ -113,27 +127,29 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for
|
||||||
const auto PWINDOW = pNode->pWindow;
|
const auto PWINDOW = pNode->pWindow;
|
||||||
// get specific gaps and rules for this workspace,
|
// get specific gaps and rules for this workspace,
|
||||||
// if user specified them in config
|
// if user specified them in config
|
||||||
const auto WORKSPACERULE = g_pConfigManager->getWorkspaceRuleFor(g_pCompositor->getWorkspaceByID(PWINDOW->m_iWorkspaceID));
|
const auto WORKSPACERULE = g_pConfigManager->getWorkspaceRuleFor(g_pCompositor->getWorkspaceByID(pNode->workspaceID));
|
||||||
|
|
||||||
|
if (!g_pCompositor->windowExists(PWINDOW)) {
|
||||||
|
Debug::log(ERR, "Node {} holding invalid {}!!", pNode, PWINDOW);
|
||||||
|
onWindowRemovedTiling(PWINDOW);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (PWINDOW->m_bIsFullscreen && !pNode->ignoreFullscreenChecks)
|
if (PWINDOW->m_bIsFullscreen && !pNode->ignoreFullscreenChecks)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
PWINDOW->updateSpecialRenderData();
|
PWINDOW->updateSpecialRenderData();
|
||||||
|
|
||||||
static auto* const PGAPSIN = &g_pConfigManager->getConfigValuePtr("general:gaps_in")->intValue;
|
static auto* const PNOGAPSWHENONLY = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("dwindle:no_gaps_when_only");
|
||||||
static auto* const PGAPSOUT = &g_pConfigManager->getConfigValuePtr("general:gaps_out")->intValue;
|
static auto* const PGAPSINDATA = (Hyprlang::CUSTOMTYPE* const*)g_pConfigManager->getConfigValuePtr("general:gaps_in");
|
||||||
static auto* const PNOGAPSWHENONLY = &g_pConfigManager->getConfigValuePtr("dwindle:no_gaps_when_only")->intValue;
|
static auto* const PGAPSOUTDATA = (Hyprlang::CUSTOMTYPE* const*)g_pConfigManager->getConfigValuePtr("general:gaps_out");
|
||||||
|
auto* const PGAPSIN = (CCssGapData*)(*PGAPSINDATA)->getData();
|
||||||
|
auto* const PGAPSOUT = (CCssGapData*)(*PGAPSOUTDATA)->getData();
|
||||||
|
|
||||||
auto gapsIn = WORKSPACERULE.gapsIn.value_or(*PGAPSIN);
|
auto gapsIn = WORKSPACERULE.gapsIn.value_or(*PGAPSIN);
|
||||||
auto gapsOut = WORKSPACERULE.gapsOut.value_or(*PGAPSOUT);
|
auto gapsOut = WORKSPACERULE.gapsOut.value_or(*PGAPSOUT);
|
||||||
|
|
||||||
if (!g_pCompositor->windowExists(PWINDOW) || !PWINDOW->m_bIsMapped) {
|
CBox nodeBox = pNode->box;
|
||||||
Debug::log(ERR, "Node {} holding invalid {}!!", pNode, PWINDOW);
|
|
||||||
onWindowRemovedTiling(PWINDOW);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
CBox nodeBox = pNode->box;
|
|
||||||
nodeBox.round();
|
nodeBox.round();
|
||||||
|
|
||||||
PWINDOW->m_vSize = nodeBox.size();
|
PWINDOW->m_vSize = nodeBox.size();
|
||||||
|
@ -141,10 +157,10 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for
|
||||||
|
|
||||||
const auto NODESONWORKSPACE = getNodesOnWorkspace(PWINDOW->m_iWorkspaceID);
|
const auto NODESONWORKSPACE = getNodesOnWorkspace(PWINDOW->m_iWorkspaceID);
|
||||||
|
|
||||||
if (*PNOGAPSWHENONLY && !g_pCompositor->isWorkspaceSpecial(PWINDOW->m_iWorkspaceID) &&
|
if (**PNOGAPSWHENONLY && !g_pCompositor->isWorkspaceSpecial(PWINDOW->m_iWorkspaceID) &&
|
||||||
(NODESONWORKSPACE == 1 || (PWINDOW->m_bIsFullscreen && g_pCompositor->getWorkspaceByID(PWINDOW->m_iWorkspaceID)->m_efFullscreenMode == FULLSCREEN_MAXIMIZED))) {
|
(NODESONWORKSPACE == 1 || (PWINDOW->m_bIsFullscreen && g_pCompositor->getWorkspaceByID(PWINDOW->m_iWorkspaceID)->m_efFullscreenMode == FULLSCREEN_MAXIMIZED))) {
|
||||||
|
|
||||||
PWINDOW->m_sSpecialRenderData.border = WORKSPACERULE.border.value_or(*PNOGAPSWHENONLY == 2);
|
PWINDOW->m_sSpecialRenderData.border = WORKSPACERULE.border.value_or(**PNOGAPSWHENONLY == 2);
|
||||||
PWINDOW->m_sSpecialRenderData.decorate = WORKSPACERULE.decorate.value_or(true);
|
PWINDOW->m_sSpecialRenderData.decorate = WORKSPACERULE.decorate.value_or(true);
|
||||||
PWINDOW->m_sSpecialRenderData.rounding = false;
|
PWINDOW->m_sSpecialRenderData.rounding = false;
|
||||||
PWINDOW->m_sSpecialRenderData.shadow = false;
|
PWINDOW->m_sSpecialRenderData.shadow = false;
|
||||||
|
@ -156,7 +172,7 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for
|
||||||
PWINDOW->m_vRealPosition = PWINDOW->m_vPosition + RESERVED.topLeft;
|
PWINDOW->m_vRealPosition = PWINDOW->m_vPosition + RESERVED.topLeft;
|
||||||
PWINDOW->m_vRealSize = PWINDOW->m_vSize - (RESERVED.topLeft + RESERVED.bottomRight);
|
PWINDOW->m_vRealSize = PWINDOW->m_vSize - (RESERVED.topLeft + RESERVED.bottomRight);
|
||||||
|
|
||||||
g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goalv());
|
g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goal());
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -164,9 +180,9 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for
|
||||||
auto calcPos = PWINDOW->m_vPosition;
|
auto calcPos = PWINDOW->m_vPosition;
|
||||||
auto calcSize = PWINDOW->m_vSize;
|
auto calcSize = PWINDOW->m_vSize;
|
||||||
|
|
||||||
const auto OFFSETTOPLEFT = Vector2D(DISPLAYLEFT ? gapsOut : gapsIn, DISPLAYTOP ? gapsOut : gapsIn);
|
const auto OFFSETTOPLEFT = Vector2D(DISPLAYLEFT ? gapsOut.left : gapsIn.left, DISPLAYTOP ? gapsOut.top : gapsIn.top);
|
||||||
|
|
||||||
const auto OFFSETBOTTOMRIGHT = Vector2D(DISPLAYRIGHT ? gapsOut : gapsIn, DISPLAYBOTTOM ? gapsOut : gapsIn);
|
const auto OFFSETBOTTOMRIGHT = Vector2D(DISPLAYRIGHT ? gapsOut.right : gapsIn.right, DISPLAYBOTTOM ? gapsOut.bottom : gapsIn.bottom);
|
||||||
|
|
||||||
calcPos = calcPos + OFFSETTOPLEFT;
|
calcPos = calcPos + OFFSETTOPLEFT;
|
||||||
calcSize = calcSize - OFFSETTOPLEFT - OFFSETBOTTOMRIGHT;
|
calcSize = calcSize - OFFSETTOPLEFT - OFFSETBOTTOMRIGHT;
|
||||||
|
@ -201,9 +217,9 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for
|
||||||
|
|
||||||
if (g_pCompositor->isWorkspaceSpecial(PWINDOW->m_iWorkspaceID)) {
|
if (g_pCompositor->isWorkspaceSpecial(PWINDOW->m_iWorkspaceID)) {
|
||||||
// if special, we adjust the coords a bit
|
// if special, we adjust the coords a bit
|
||||||
static auto* const PSCALEFACTOR = &g_pConfigManager->getConfigValuePtr("dwindle:special_scale_factor")->floatValue;
|
static auto* const PSCALEFACTOR = (Hyprlang::FLOAT* const*)g_pConfigManager->getConfigValuePtr("dwindle:special_scale_factor");
|
||||||
|
|
||||||
CBox wb = {calcPos + (calcSize - calcSize * *PSCALEFACTOR) / 2.f, calcSize * *PSCALEFACTOR};
|
CBox wb = {calcPos + (calcSize - calcSize * **PSCALEFACTOR) / 2.f, calcSize * **PSCALEFACTOR};
|
||||||
wb.round(); // avoid rounding mess
|
wb.round(); // avoid rounding mess
|
||||||
|
|
||||||
PWINDOW->m_vRealPosition = wb.pos();
|
PWINDOW->m_vRealPosition = wb.pos();
|
||||||
|
@ -211,10 +227,13 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for
|
||||||
|
|
||||||
g_pXWaylandManager->setWindowSize(PWINDOW, wb.size());
|
g_pXWaylandManager->setWindowSize(PWINDOW, wb.size());
|
||||||
} else {
|
} else {
|
||||||
PWINDOW->m_vRealSize = calcSize;
|
CBox wb = {calcPos, calcSize};
|
||||||
PWINDOW->m_vRealPosition = calcPos;
|
wb.round(); // avoid rounding mess
|
||||||
|
|
||||||
g_pXWaylandManager->setWindowSize(PWINDOW, calcSize);
|
PWINDOW->m_vRealSize = wb.size();
|
||||||
|
PWINDOW->m_vRealPosition = wb.pos();
|
||||||
|
|
||||||
|
g_pXWaylandManager->setWindowSize(PWINDOW, wb.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (force) {
|
if (force) {
|
||||||
|
@ -238,8 +257,8 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection dire
|
||||||
|
|
||||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID);
|
const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID);
|
||||||
|
|
||||||
static auto* const PUSEACTIVE = &g_pConfigManager->getConfigValuePtr("dwindle:use_active_for_splits")->intValue;
|
static auto* const PUSEACTIVE = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("dwindle:use_active_for_splits");
|
||||||
static auto* const PDEFAULTSPLIT = &g_pConfigManager->getConfigValuePtr("dwindle:default_split_ratio")->floatValue;
|
static auto* const PDEFAULTSPLIT = (Hyprlang::FLOAT* const*)g_pConfigManager->getConfigValuePtr("dwindle:default_split_ratio");
|
||||||
|
|
||||||
if (direction != DIRECTION_DEFAULT && overrideDirection == DIRECTION_DEFAULT)
|
if (direction != DIRECTION_DEFAULT && overrideDirection == DIRECTION_DEFAULT)
|
||||||
overrideDirection = direction;
|
overrideDirection = direction;
|
||||||
|
@ -254,26 +273,25 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection dire
|
||||||
|
|
||||||
const auto MOUSECOORDS = m_vOverrideFocalPoint.value_or(g_pInputManager->getMouseCoordsInternal());
|
const auto MOUSECOORDS = m_vOverrideFocalPoint.value_or(g_pInputManager->getMouseCoordsInternal());
|
||||||
const auto MONFROMCURSOR = g_pCompositor->getMonitorFromVector(MOUSECOORDS);
|
const auto MONFROMCURSOR = g_pCompositor->getMonitorFromVector(MOUSECOORDS);
|
||||||
const auto TARGETCOORDS = PMONITOR->ID == MONFROMCURSOR->ID && g_pCompositor->isPointOnReservedArea(MOUSECOORDS, PMONITOR) ? pWindow->middle() : MOUSECOORDS;
|
|
||||||
|
|
||||||
if (PMONITOR->ID == MONFROMCURSOR->ID &&
|
if (PMONITOR->ID == MONFROMCURSOR->ID &&
|
||||||
(PNODE->workspaceID == PMONITOR->activeWorkspace || (g_pCompositor->isWorkspaceSpecial(PNODE->workspaceID) && PMONITOR->specialWorkspaceID)) && !*PUSEACTIVE) {
|
(PNODE->workspaceID == PMONITOR->activeWorkspace || (g_pCompositor->isWorkspaceSpecial(PNODE->workspaceID) && PMONITOR->specialWorkspaceID)) && !**PUSEACTIVE) {
|
||||||
OPENINGON = getNodeFromWindow(g_pCompositor->vectorToWindowTiled(TARGETCOORDS));
|
OPENINGON = getNodeFromWindow(g_pCompositor->vectorToWindowUnified(MOUSECOORDS, RESERVED_EXTENTS | INPUT_EXTENTS));
|
||||||
|
|
||||||
// happens on reserved area
|
if (!OPENINGON && g_pCompositor->isPointOnReservedArea(MOUSECOORDS, PMONITOR))
|
||||||
if (!OPENINGON && g_pCompositor->getWindowsOnWorkspace(PNODE->workspaceID) > 0)
|
OPENINGON = getClosestNodeOnWorkspace(PNODE->workspaceID, MOUSECOORDS);
|
||||||
OPENINGON = getFirstNodeOnWorkspace(PMONITOR->activeWorkspace);
|
|
||||||
|
|
||||||
} else if (*PUSEACTIVE) {
|
} else if (**PUSEACTIVE) {
|
||||||
if (g_pCompositor->m_pLastWindow && !g_pCompositor->m_pLastWindow->m_bIsFloating && g_pCompositor->m_pLastWindow != pWindow &&
|
if (g_pCompositor->m_pLastWindow && !g_pCompositor->m_pLastWindow->m_bIsFloating && g_pCompositor->m_pLastWindow != pWindow &&
|
||||||
g_pCompositor->m_pLastWindow->m_iWorkspaceID == pWindow->m_iWorkspaceID && g_pCompositor->m_pLastWindow->m_bIsMapped) {
|
g_pCompositor->m_pLastWindow->m_iWorkspaceID == pWindow->m_iWorkspaceID && g_pCompositor->m_pLastWindow->m_bIsMapped) {
|
||||||
OPENINGON = getNodeFromWindow(g_pCompositor->m_pLastWindow);
|
OPENINGON = getNodeFromWindow(g_pCompositor->m_pLastWindow);
|
||||||
} else {
|
} else {
|
||||||
OPENINGON = getNodeFromWindow(g_pCompositor->vectorToWindowTiled(TARGETCOORDS));
|
OPENINGON = getNodeFromWindow(g_pCompositor->vectorToWindowUnified(MOUSECOORDS, RESERVED_EXTENTS | INPUT_EXTENTS));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!OPENINGON && g_pCompositor->getWindowsOnWorkspace(PNODE->workspaceID) > 0)
|
if (!OPENINGON && g_pCompositor->isPointOnReservedArea(MOUSECOORDS, PMONITOR))
|
||||||
OPENINGON = getFirstNodeOnWorkspace(PMONITOR->activeWorkspace);
|
OPENINGON = getClosestNodeOnWorkspace(PNODE->workspaceID, MOUSECOORDS);
|
||||||
|
|
||||||
} else
|
} else
|
||||||
OPENINGON = getFirstNodeOnWorkspace(pWindow->m_iWorkspaceID);
|
OPENINGON = getFirstNodeOnWorkspace(pWindow->m_iWorkspaceID);
|
||||||
|
|
||||||
|
@ -325,8 +343,8 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection dire
|
||||||
&& pWindow->canBeGroupedInto(OPENINGON->pWindow) && !m_vOverrideFocalPoint) { // we are not moving window
|
&& pWindow->canBeGroupedInto(OPENINGON->pWindow) && !m_vOverrideFocalPoint) { // we are not moving window
|
||||||
m_lDwindleNodesData.remove(*PNODE);
|
m_lDwindleNodesData.remove(*PNODE);
|
||||||
|
|
||||||
static const auto* USECURRPOS = &g_pConfigManager->getConfigValuePtr("group:insert_after_current")->intValue;
|
static const auto* USECURRPOS = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("group:insert_after_current");
|
||||||
(*USECURRPOS ? OPENINGON->pWindow : OPENINGON->pWindow->getGroupTail())->insertWindowToGroup(pWindow);
|
(**USECURRPOS ? OPENINGON->pWindow : OPENINGON->pWindow->getGroupTail())->insertWindowToGroup(pWindow);
|
||||||
|
|
||||||
OPENINGON->pWindow->setGroupCurrent(pWindow);
|
OPENINGON->pWindow->setGroupCurrent(pWindow);
|
||||||
pWindow->applyGroupRules();
|
pWindow->applyGroupRules();
|
||||||
|
@ -349,17 +367,17 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection dire
|
||||||
NEWPARENT->workspaceID = OPENINGON->workspaceID;
|
NEWPARENT->workspaceID = OPENINGON->workspaceID;
|
||||||
NEWPARENT->pParent = OPENINGON->pParent;
|
NEWPARENT->pParent = OPENINGON->pParent;
|
||||||
NEWPARENT->isNode = true; // it is a node
|
NEWPARENT->isNode = true; // it is a node
|
||||||
NEWPARENT->splitRatio = std::clamp(*PDEFAULTSPLIT, 0.1f, 1.9f);
|
NEWPARENT->splitRatio = std::clamp(**PDEFAULTSPLIT, 0.1f, 1.9f);
|
||||||
|
|
||||||
const auto PWIDTHMULTIPLIER = &g_pConfigManager->getConfigValuePtr("dwindle:split_width_multiplier")->floatValue;
|
const auto PWIDTHMULTIPLIER = (Hyprlang::FLOAT* const*)g_pConfigManager->getConfigValuePtr("dwindle:split_width_multiplier");
|
||||||
|
|
||||||
// if cursor over first child, make it first, etc
|
// if cursor over first child, make it first, etc
|
||||||
const auto SIDEBYSIDE = NEWPARENT->box.w > NEWPARENT->box.h * *PWIDTHMULTIPLIER;
|
const auto SIDEBYSIDE = NEWPARENT->box.w > NEWPARENT->box.h * **PWIDTHMULTIPLIER;
|
||||||
NEWPARENT->splitTop = !SIDEBYSIDE;
|
NEWPARENT->splitTop = !SIDEBYSIDE;
|
||||||
|
|
||||||
static auto* const PFORCESPLIT = &g_pConfigManager->getConfigValuePtr("dwindle:force_split")->intValue;
|
static auto* const PFORCESPLIT = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("dwindle:force_split");
|
||||||
static auto* const PERMANENTDIRECTIONOVERRIDE = &g_pConfigManager->getConfigValuePtr("dwindle:permanent_direction_override")->intValue;
|
static auto* const PERMANENTDIRECTIONOVERRIDE = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("dwindle:permanent_direction_override");
|
||||||
static auto* const PSMARTSPLIT = &g_pConfigManager->getConfigValuePtr("dwindle:smart_split")->intValue;
|
static auto* const PSMARTSPLIT = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("dwindle:smart_split");
|
||||||
|
|
||||||
bool horizontalOverride = false;
|
bool horizontalOverride = false;
|
||||||
bool verticalOverride = false;
|
bool verticalOverride = false;
|
||||||
|
@ -383,37 +401,44 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection dire
|
||||||
}
|
}
|
||||||
|
|
||||||
// whether or not the override persists after opening one window
|
// whether or not the override persists after opening one window
|
||||||
if (*PERMANENTDIRECTIONOVERRIDE == 0)
|
if (**PERMANENTDIRECTIONOVERRIDE == 0)
|
||||||
overrideDirection = DIRECTION_DEFAULT;
|
overrideDirection = DIRECTION_DEFAULT;
|
||||||
} else if (*PSMARTSPLIT == 1) {
|
} else if (**PSMARTSPLIT == 1) {
|
||||||
const auto tl = NEWPARENT->box.pos();
|
const auto PARENT_CENTER = NEWPARENT->box.pos() + NEWPARENT->box.size() / 2;
|
||||||
const auto tr = NEWPARENT->box.pos() + Vector2D(NEWPARENT->box.w, 0);
|
const auto PARENT_PROPORTIONS = NEWPARENT->box.h / NEWPARENT->box.w;
|
||||||
const auto bl = NEWPARENT->box.pos() + Vector2D(0, NEWPARENT->box.h);
|
const auto DELTA = MOUSECOORDS - PARENT_CENTER;
|
||||||
const auto br = NEWPARENT->box.pos() + NEWPARENT->box.size();
|
const auto DELTA_SLOPE = DELTA.y / DELTA.x;
|
||||||
const auto cc = NEWPARENT->box.pos() + NEWPARENT->box.size() / 2;
|
|
||||||
|
|
||||||
if (TARGETCOORDS.inTriangle(tl, tr, cc)) {
|
if (abs(DELTA_SLOPE) < PARENT_PROPORTIONS) {
|
||||||
NEWPARENT->splitTop = true;
|
if (DELTA.x > 0) {
|
||||||
NEWPARENT->children[0] = PNODE;
|
// right
|
||||||
NEWPARENT->children[1] = OPENINGON;
|
NEWPARENT->splitTop = false;
|
||||||
} else if (TARGETCOORDS.inTriangle(tr, cc, br)) {
|
NEWPARENT->children[0] = OPENINGON;
|
||||||
NEWPARENT->splitTop = false;
|
NEWPARENT->children[1] = PNODE;
|
||||||
NEWPARENT->children[0] = OPENINGON;
|
} else {
|
||||||
NEWPARENT->children[1] = PNODE;
|
// left
|
||||||
} else if (TARGETCOORDS.inTriangle(br, bl, cc)) {
|
NEWPARENT->splitTop = false;
|
||||||
NEWPARENT->splitTop = true;
|
NEWPARENT->children[0] = PNODE;
|
||||||
NEWPARENT->children[0] = OPENINGON;
|
NEWPARENT->children[1] = OPENINGON;
|
||||||
NEWPARENT->children[1] = PNODE;
|
}
|
||||||
} else {
|
} else {
|
||||||
NEWPARENT->splitTop = false;
|
if (DELTA.y > 0) {
|
||||||
NEWPARENT->children[0] = PNODE;
|
// bottom
|
||||||
NEWPARENT->children[1] = OPENINGON;
|
NEWPARENT->splitTop = true;
|
||||||
|
NEWPARENT->children[0] = OPENINGON;
|
||||||
|
NEWPARENT->children[1] = PNODE;
|
||||||
|
} else {
|
||||||
|
// top
|
||||||
|
NEWPARENT->splitTop = true;
|
||||||
|
NEWPARENT->children[0] = PNODE;
|
||||||
|
NEWPARENT->children[1] = OPENINGON;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (*PFORCESPLIT == 0 || !pWindow->m_bFirstMap) {
|
} else if (**PFORCESPLIT == 0 || !pWindow->m_bFirstMap) {
|
||||||
if ((SIDEBYSIDE &&
|
if ((SIDEBYSIDE &&
|
||||||
VECINRECT(TARGETCOORDS, NEWPARENT->box.x, NEWPARENT->box.y / *PWIDTHMULTIPLIER, NEWPARENT->box.x + NEWPARENT->box.w / 2.f, NEWPARENT->box.y + NEWPARENT->box.h)) ||
|
VECINRECT(MOUSECOORDS, NEWPARENT->box.x, NEWPARENT->box.y / **PWIDTHMULTIPLIER, NEWPARENT->box.x + NEWPARENT->box.w / 2.f, NEWPARENT->box.y + NEWPARENT->box.h)) ||
|
||||||
(!SIDEBYSIDE &&
|
(!SIDEBYSIDE &&
|
||||||
VECINRECT(TARGETCOORDS, NEWPARENT->box.x, NEWPARENT->box.y / *PWIDTHMULTIPLIER, NEWPARENT->box.x + NEWPARENT->box.w, NEWPARENT->box.y + NEWPARENT->box.h / 2.f))) {
|
VECINRECT(MOUSECOORDS, NEWPARENT->box.x, NEWPARENT->box.y / **PWIDTHMULTIPLIER, NEWPARENT->box.x + NEWPARENT->box.w, NEWPARENT->box.y + NEWPARENT->box.h / 2.f))) {
|
||||||
// we are hovering over the first node, make PNODE first.
|
// we are hovering over the first node, make PNODE first.
|
||||||
NEWPARENT->children[1] = OPENINGON;
|
NEWPARENT->children[1] = OPENINGON;
|
||||||
NEWPARENT->children[0] = PNODE;
|
NEWPARENT->children[0] = PNODE;
|
||||||
|
@ -423,7 +448,7 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection dire
|
||||||
NEWPARENT->children[1] = PNODE;
|
NEWPARENT->children[1] = PNODE;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (*PFORCESPLIT == 1) {
|
if (**PFORCESPLIT == 1) {
|
||||||
NEWPARENT->children[1] = OPENINGON;
|
NEWPARENT->children[1] = OPENINGON;
|
||||||
NEWPARENT->children[0] = PNODE;
|
NEWPARENT->children[0] = PNODE;
|
||||||
} else {
|
} else {
|
||||||
|
@ -442,7 +467,7 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection dire
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the children
|
// Update the children
|
||||||
if (!verticalOverride && (NEWPARENT->box.w * *PWIDTHMULTIPLIER > NEWPARENT->box.h || horizontalOverride)) {
|
if (!verticalOverride && (NEWPARENT->box.w * **PWIDTHMULTIPLIER > NEWPARENT->box.h || horizontalOverride)) {
|
||||||
// split left/right -> forced
|
// split left/right -> forced
|
||||||
OPENINGON->box = {NEWPARENT->box.pos(), Vector2D(NEWPARENT->box.w / 2.f, NEWPARENT->box.h)};
|
OPENINGON->box = {NEWPARENT->box.pos(), Vector2D(NEWPARENT->box.w / 2.f, NEWPARENT->box.h)};
|
||||||
PNODE->box = {Vector2D(NEWPARENT->box.x + NEWPARENT->box.w / 2.f, NEWPARENT->box.y), Vector2D(NEWPARENT->box.w / 2.f, NEWPARENT->box.h)};
|
PNODE->box = {Vector2D(NEWPARENT->box.x + NEWPARENT->box.w / 2.f, NEWPARENT->box.y), Vector2D(NEWPARENT->box.w / 2.f, NEWPARENT->box.h)};
|
||||||
|
@ -581,13 +606,13 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorn
|
||||||
const auto PNODE = getNodeFromWindow(PWINDOW);
|
const auto PNODE = getNodeFromWindow(PWINDOW);
|
||||||
|
|
||||||
if (!PNODE) {
|
if (!PNODE) {
|
||||||
PWINDOW->m_vRealSize = Vector2D(std::max((PWINDOW->m_vRealSize.goalv() + pixResize).x, 20.0), std::max((PWINDOW->m_vRealSize.goalv() + pixResize).y, 20.0));
|
PWINDOW->m_vRealSize = Vector2D(std::max((PWINDOW->m_vRealSize.goal() + pixResize).x, 20.0), std::max((PWINDOW->m_vRealSize.goal() + pixResize).y, 20.0));
|
||||||
PWINDOW->updateWindowDecos();
|
PWINDOW->updateWindowDecos();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto PANIMATE = &g_pConfigManager->getConfigValuePtr("misc:animate_manual_resizes")->intValue;
|
const auto PANIMATE = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("misc:animate_manual_resizes");
|
||||||
const auto PSMARTRESIZING = &g_pConfigManager->getConfigValuePtr("dwindle:smart_resizing")->intValue;
|
const auto PSMARTRESIZING = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("dwindle:smart_resizing");
|
||||||
|
|
||||||
// get some data about our window
|
// get some data about our window
|
||||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID);
|
const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID);
|
||||||
|
@ -600,7 +625,7 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorn
|
||||||
if (!m_PseudoDragFlags.started) {
|
if (!m_PseudoDragFlags.started) {
|
||||||
m_PseudoDragFlags.started = true;
|
m_PseudoDragFlags.started = true;
|
||||||
|
|
||||||
const auto pseudoSize = PWINDOW->m_vRealSize.goalv();
|
const auto pseudoSize = PWINDOW->m_vRealSize.goal();
|
||||||
const auto mouseOffset = g_pInputManager->getMouseCoordsInternal() - (PNODE->box.pos() + ((PNODE->box.size() / 2) - (pseudoSize / 2)));
|
const auto mouseOffset = g_pInputManager->getMouseCoordsInternal() - (PNODE->box.pos() + ((PNODE->box.size() / 2) - (pseudoSize / 2)));
|
||||||
|
|
||||||
if (mouseOffset.x > 0 && mouseOffset.x < pseudoSize.x && mouseOffset.y > 0 && mouseOffset.y < pseudoSize.y) {
|
if (mouseOffset.x > 0 && mouseOffset.x < pseudoSize.x && mouseOffset.y > 0 && mouseOffset.y < pseudoSize.y) {
|
||||||
|
@ -624,11 +649,13 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorn
|
||||||
else
|
else
|
||||||
PWINDOW->m_vPseudoSize.y -= pixResize.y * 2;
|
PWINDOW->m_vPseudoSize.y -= pixResize.y * 2;
|
||||||
|
|
||||||
PWINDOW->m_vPseudoSize.x = std::clamp(PWINDOW->m_vPseudoSize.x, 30.0, PNODE->box.w);
|
CBox wbox = PNODE->box;
|
||||||
PWINDOW->m_vPseudoSize.y = std::clamp(PWINDOW->m_vPseudoSize.y, 30.0, PNODE->box.h);
|
wbox.round();
|
||||||
|
|
||||||
|
PWINDOW->m_vPseudoSize = {std::clamp(PWINDOW->m_vPseudoSize.x, 30.0, wbox.w), std::clamp(PWINDOW->m_vPseudoSize.y, 30.0, wbox.h)};
|
||||||
|
|
||||||
PWINDOW->m_vLastFloatingSize = PWINDOW->m_vPseudoSize;
|
PWINDOW->m_vLastFloatingSize = PWINDOW->m_vPseudoSize;
|
||||||
PNODE->recalcSizePosRecursive(*PANIMATE == 0);
|
PNODE->recalcSizePosRecursive(**PANIMATE == 0);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -642,7 +669,7 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorn
|
||||||
if (DISPLAYBOTTOM && DISPLAYTOP)
|
if (DISPLAYBOTTOM && DISPLAYTOP)
|
||||||
allowedMovement.y = 0;
|
allowedMovement.y = 0;
|
||||||
|
|
||||||
if (*PSMARTRESIZING == 1) {
|
if (**PSMARTRESIZING == 1) {
|
||||||
// Identify inner and outer nodes for both directions
|
// Identify inner and outer nodes for both directions
|
||||||
SDwindleNodeData* PVOUTER = nullptr;
|
SDwindleNodeData* PVOUTER = nullptr;
|
||||||
SDwindleNodeData* PVINNER = nullptr;
|
SDwindleNodeData* PVINNER = nullptr;
|
||||||
|
@ -676,14 +703,14 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorn
|
||||||
|
|
||||||
if (PHINNER) {
|
if (PHINNER) {
|
||||||
const auto ORIGINAL = PHINNER->box.w;
|
const auto ORIGINAL = PHINNER->box.w;
|
||||||
PHOUTER->pParent->recalcSizePosRecursive(*PANIMATE == 0);
|
PHOUTER->pParent->recalcSizePosRecursive(**PANIMATE == 0);
|
||||||
if (PHINNER->pParent->children[0] == PHINNER)
|
if (PHINNER->pParent->children[0] == PHINNER)
|
||||||
PHINNER->pParent->splitRatio = std::clamp((ORIGINAL - allowedMovement.x) / PHINNER->pParent->box.w * 2.f, 0.1, 1.9);
|
PHINNER->pParent->splitRatio = std::clamp((ORIGINAL - allowedMovement.x) / PHINNER->pParent->box.w * 2.f, 0.1, 1.9);
|
||||||
else
|
else
|
||||||
PHINNER->pParent->splitRatio = std::clamp(2 - (ORIGINAL + allowedMovement.x) / PHINNER->pParent->box.w * 2.f, 0.1, 1.9);
|
PHINNER->pParent->splitRatio = std::clamp(2 - (ORIGINAL + allowedMovement.x) / PHINNER->pParent->box.w * 2.f, 0.1, 1.9);
|
||||||
PHINNER->pParent->recalcSizePosRecursive(*PANIMATE == 0);
|
PHINNER->pParent->recalcSizePosRecursive(**PANIMATE == 0);
|
||||||
} else
|
} else
|
||||||
PHOUTER->pParent->recalcSizePosRecursive(*PANIMATE == 0);
|
PHOUTER->pParent->recalcSizePosRecursive(**PANIMATE == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PVOUTER) {
|
if (PVOUTER) {
|
||||||
|
@ -691,14 +718,14 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorn
|
||||||
|
|
||||||
if (PVINNER) {
|
if (PVINNER) {
|
||||||
const auto ORIGINAL = PVINNER->box.h;
|
const auto ORIGINAL = PVINNER->box.h;
|
||||||
PVOUTER->pParent->recalcSizePosRecursive(*PANIMATE == 0);
|
PVOUTER->pParent->recalcSizePosRecursive(**PANIMATE == 0);
|
||||||
if (PVINNER->pParent->children[0] == PVINNER)
|
if (PVINNER->pParent->children[0] == PVINNER)
|
||||||
PVINNER->pParent->splitRatio = std::clamp((ORIGINAL - allowedMovement.y) / PVINNER->pParent->box.h * 2.f, 0.1, 1.9);
|
PVINNER->pParent->splitRatio = std::clamp((ORIGINAL - allowedMovement.y) / PVINNER->pParent->box.h * 2.f, 0.1, 1.9);
|
||||||
else
|
else
|
||||||
PVINNER->pParent->splitRatio = std::clamp(2 - (ORIGINAL + allowedMovement.y) / PVINNER->pParent->box.h * 2.f, 0.1, 1.9);
|
PVINNER->pParent->splitRatio = std::clamp(2 - (ORIGINAL + allowedMovement.y) / PVINNER->pParent->box.h * 2.f, 0.1, 1.9);
|
||||||
PVINNER->pParent->recalcSizePosRecursive(*PANIMATE == 0);
|
PVINNER->pParent->recalcSizePosRecursive(**PANIMATE == 0);
|
||||||
} else
|
} else
|
||||||
PVOUTER->pParent->recalcSizePosRecursive(*PANIMATE == 0);
|
PVOUTER->pParent->recalcSizePosRecursive(**PANIMATE == 0);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// get the correct containers to apply splitratio to
|
// get the correct containers to apply splitratio to
|
||||||
|
@ -717,11 +744,11 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorn
|
||||||
if (PARENTSIDEBYSIDE) {
|
if (PARENTSIDEBYSIDE) {
|
||||||
allowedMovement.x *= 2.f / PPARENT->box.w;
|
allowedMovement.x *= 2.f / PPARENT->box.w;
|
||||||
PPARENT->splitRatio = std::clamp(PPARENT->splitRatio + allowedMovement.x, 0.1, 1.9);
|
PPARENT->splitRatio = std::clamp(PPARENT->splitRatio + allowedMovement.x, 0.1, 1.9);
|
||||||
PPARENT->recalcSizePosRecursive(*PANIMATE == 0);
|
PPARENT->recalcSizePosRecursive(**PANIMATE == 0);
|
||||||
} else {
|
} else {
|
||||||
allowedMovement.y *= 2.f / PPARENT->box.h;
|
allowedMovement.y *= 2.f / PPARENT->box.h;
|
||||||
PPARENT->splitRatio = std::clamp(PPARENT->splitRatio + allowedMovement.y, 0.1, 1.9);
|
PPARENT->splitRatio = std::clamp(PPARENT->splitRatio + allowedMovement.y, 0.1, 1.9);
|
||||||
PPARENT->recalcSizePosRecursive(*PANIMATE == 0);
|
PPARENT->recalcSizePosRecursive(**PANIMATE == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
@ -736,11 +763,11 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorn
|
||||||
if (PARENTSIDEBYSIDE) {
|
if (PARENTSIDEBYSIDE) {
|
||||||
allowedMovement.x *= 2.f / PPARENT->box.w;
|
allowedMovement.x *= 2.f / PPARENT->box.w;
|
||||||
PPARENT->splitRatio = std::clamp(PPARENT->splitRatio + allowedMovement.x, 0.1, 1.9);
|
PPARENT->splitRatio = std::clamp(PPARENT->splitRatio + allowedMovement.x, 0.1, 1.9);
|
||||||
PPARENT->recalcSizePosRecursive(*PANIMATE == 0);
|
PPARENT->recalcSizePosRecursive(**PANIMATE == 0);
|
||||||
} else {
|
} else {
|
||||||
allowedMovement.y *= 2.f / PPARENT->box.h;
|
allowedMovement.y *= 2.f / PPARENT->box.h;
|
||||||
PPARENT->splitRatio = std::clamp(PPARENT->splitRatio + allowedMovement.y, 0.1, 1.9);
|
PPARENT->splitRatio = std::clamp(PPARENT->splitRatio + allowedMovement.y, 0.1, 1.9);
|
||||||
PPARENT->recalcSizePosRecursive(*PANIMATE == 0);
|
PPARENT->recalcSizePosRecursive(**PANIMATE == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
@ -755,8 +782,8 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorn
|
||||||
|
|
||||||
SIDECONTAINER->splitRatio = std::clamp(SIDECONTAINER->splitRatio + allowedMovement.x, 0.1, 1.9);
|
SIDECONTAINER->splitRatio = std::clamp(SIDECONTAINER->splitRatio + allowedMovement.x, 0.1, 1.9);
|
||||||
TOPCONTAINER->splitRatio = std::clamp(TOPCONTAINER->splitRatio + allowedMovement.y, 0.1, 1.9);
|
TOPCONTAINER->splitRatio = std::clamp(TOPCONTAINER->splitRatio + allowedMovement.y, 0.1, 1.9);
|
||||||
SIDECONTAINER->recalcSizePosRecursive(*PANIMATE == 0);
|
SIDECONTAINER->recalcSizePosRecursive(**PANIMATE == 0);
|
||||||
TOPCONTAINER->recalcSizePosRecursive(*PANIMATE == 0);
|
TOPCONTAINER->recalcSizePosRecursive(**PANIMATE == 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -776,10 +803,21 @@ void CHyprDwindleLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscree
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// save position and size if floating
|
||||||
|
if (pWindow->m_bIsFloating && on) {
|
||||||
|
pWindow->m_vLastFloatingSize = pWindow->m_vRealSize.goal();
|
||||||
|
pWindow->m_vLastFloatingPosition = pWindow->m_vRealPosition.goal();
|
||||||
|
pWindow->m_vPosition = pWindow->m_vRealPosition.goal();
|
||||||
|
pWindow->m_vSize = pWindow->m_vRealSize.goal();
|
||||||
|
}
|
||||||
|
|
||||||
// otherwise, accept it.
|
// otherwise, accept it.
|
||||||
pWindow->m_bIsFullscreen = on;
|
pWindow->m_bIsFullscreen = on;
|
||||||
PWORKSPACE->m_bHasFullscreenWindow = !PWORKSPACE->m_bHasFullscreenWindow;
|
PWORKSPACE->m_bHasFullscreenWindow = !PWORKSPACE->m_bHasFullscreenWindow;
|
||||||
|
|
||||||
|
pWindow->updateDynamicRules();
|
||||||
|
pWindow->updateWindowDecos();
|
||||||
|
|
||||||
g_pEventManager->postEvent(SHyprIPCEvent{"fullscreen", std::to_string((int)on)});
|
g_pEventManager->postEvent(SHyprIPCEvent{"fullscreen", std::to_string((int)on)});
|
||||||
EMIT_HOOK_EVENT("fullscreen", pWindow);
|
EMIT_HOOK_EVENT("fullscreen", pWindow);
|
||||||
|
|
||||||
|
@ -800,14 +838,6 @@ void CHyprDwindleLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscree
|
||||||
|
|
||||||
PWORKSPACE->m_efFullscreenMode = fullscreenMode;
|
PWORKSPACE->m_efFullscreenMode = fullscreenMode;
|
||||||
|
|
||||||
// save position and size if floating
|
|
||||||
if (pWindow->m_bIsFloating) {
|
|
||||||
pWindow->m_vLastFloatingSize = pWindow->m_vRealSize.goalv();
|
|
||||||
pWindow->m_vLastFloatingPosition = pWindow->m_vRealPosition.goalv();
|
|
||||||
pWindow->m_vPosition = pWindow->m_vRealPosition.goalv();
|
|
||||||
pWindow->m_vSize = pWindow->m_vRealSize.goalv();
|
|
||||||
}
|
|
||||||
|
|
||||||
// apply new pos and size being monitors' box
|
// apply new pos and size being monitors' box
|
||||||
if (fullscreenMode == FULLSCREEN_FULL) {
|
if (fullscreenMode == FULLSCREEN_FULL) {
|
||||||
pWindow->m_vRealPosition = PMONITOR->vecPosition;
|
pWindow->m_vRealPosition = PMONITOR->vecPosition;
|
||||||
|
@ -824,13 +854,13 @@ void CHyprDwindleLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscree
|
||||||
pWindow->m_vPosition = fakeNode.box.pos();
|
pWindow->m_vPosition = fakeNode.box.pos();
|
||||||
pWindow->m_vSize = fakeNode.box.size();
|
pWindow->m_vSize = fakeNode.box.size();
|
||||||
|
|
||||||
applyNodeDataToWindow(&fakeNode);
|
applyNodeDataToWindow(&fakeNode, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
g_pCompositor->updateWindowAnimatedDecorationValues(pWindow);
|
g_pCompositor->updateWindowAnimatedDecorationValues(pWindow);
|
||||||
|
|
||||||
g_pXWaylandManager->setWindowSize(pWindow, pWindow->m_vRealSize.goalv());
|
g_pXWaylandManager->setWindowSize(pWindow, pWindow->m_vRealSize.goal());
|
||||||
|
|
||||||
g_pCompositor->changeWindowZOrder(pWindow, true);
|
g_pCompositor->changeWindowZOrder(pWindow, true);
|
||||||
|
|
||||||
|
@ -967,6 +997,8 @@ std::any CHyprDwindleLayout::layoutMessage(SLayoutMessageHeader header, std::str
|
||||||
const auto ARGS = CVarList(message, 0, ' ');
|
const auto ARGS = CVarList(message, 0, ' ');
|
||||||
if (ARGS[0] == "togglesplit") {
|
if (ARGS[0] == "togglesplit") {
|
||||||
toggleSplit(header.pWindow);
|
toggleSplit(header.pWindow);
|
||||||
|
} else if (ARGS[0] == "swapsplit") {
|
||||||
|
swapSplit(header.pWindow);
|
||||||
} else if (ARGS[0] == "preselect") {
|
} else if (ARGS[0] == "preselect") {
|
||||||
std::string direction = ARGS[1];
|
std::string direction = ARGS[1];
|
||||||
|
|
||||||
|
@ -1020,6 +1052,20 @@ void CHyprDwindleLayout::toggleSplit(CWindow* pWindow) {
|
||||||
PNODE->pParent->recalcSizePosRecursive();
|
PNODE->pParent->recalcSizePosRecursive();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CHyprDwindleLayout::swapSplit(CWindow* pWindow) {
|
||||||
|
const auto PNODE = getNodeFromWindow(pWindow);
|
||||||
|
|
||||||
|
if (!PNODE || !PNODE->pParent)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (pWindow->m_bIsFullscreen)
|
||||||
|
return;
|
||||||
|
|
||||||
|
std::swap(PNODE->pParent->children[0], PNODE->pParent->children[1]);
|
||||||
|
|
||||||
|
PNODE->pParent->recalcSizePosRecursive();
|
||||||
|
}
|
||||||
|
|
||||||
void CHyprDwindleLayout::replaceWindowDataWith(CWindow* from, CWindow* to) {
|
void CHyprDwindleLayout::replaceWindowDataWith(CWindow* from, CWindow* to) {
|
||||||
const auto PNODE = getNodeFromWindow(from);
|
const auto PNODE = getNodeFromWindow(from);
|
||||||
|
|
||||||
|
@ -1047,3 +1093,53 @@ void CHyprDwindleLayout::onEnable() {
|
||||||
void CHyprDwindleLayout::onDisable() {
|
void CHyprDwindleLayout::onDisable() {
|
||||||
m_lDwindleNodesData.clear();
|
m_lDwindleNodesData.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Vector2D CHyprDwindleLayout::predictSizeForNewWindow() {
|
||||||
|
if (!g_pCompositor->m_pLastMonitor)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
// get window candidate
|
||||||
|
CWindow* candidate = g_pCompositor->m_pLastWindow;
|
||||||
|
|
||||||
|
if (!candidate)
|
||||||
|
candidate = g_pCompositor->getFirstWindowOnWorkspace(g_pCompositor->m_pLastMonitor->activeWorkspace);
|
||||||
|
|
||||||
|
// create a fake node
|
||||||
|
SDwindleNodeData node;
|
||||||
|
|
||||||
|
if (!candidate)
|
||||||
|
return g_pCompositor->m_pLastMonitor->vecSize;
|
||||||
|
else {
|
||||||
|
const auto PNODE = getNodeFromWindow(candidate);
|
||||||
|
|
||||||
|
if (!PNODE)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
node = *PNODE;
|
||||||
|
node.pWindow = nullptr;
|
||||||
|
|
||||||
|
CBox box = PNODE->box;
|
||||||
|
|
||||||
|
static auto* const PSMARTSPLIT = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("dwindle:smart_split");
|
||||||
|
static auto* const PPRESERVESPLIT = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("dwindle:preserve_split");
|
||||||
|
static auto* const PFLMULT = (Hyprlang::FLOAT* const*)g_pConfigManager->getConfigValuePtr("dwindle:split_width_multiplier");
|
||||||
|
|
||||||
|
bool splitTop = false;
|
||||||
|
|
||||||
|
if (**PPRESERVESPLIT == 0 && **PSMARTSPLIT == 0)
|
||||||
|
splitTop = box.h * **PFLMULT > box.w;
|
||||||
|
|
||||||
|
const auto SPLITSIDE = !splitTop;
|
||||||
|
|
||||||
|
if (SPLITSIDE)
|
||||||
|
node.box = {{}, {box.w / 2.0, box.h}};
|
||||||
|
else
|
||||||
|
node.box = {{}, {box.w, box.h / 2.0}};
|
||||||
|
|
||||||
|
// TODO: make this better and more accurate
|
||||||
|
|
||||||
|
return node.box.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
|
@ -59,6 +59,7 @@ class CHyprDwindleLayout : public IHyprLayout {
|
||||||
virtual void alterSplitRatio(CWindow*, float, bool);
|
virtual void alterSplitRatio(CWindow*, float, bool);
|
||||||
virtual std::string getLayoutName();
|
virtual std::string getLayoutName();
|
||||||
virtual void replaceWindowDataWith(CWindow* from, CWindow* to);
|
virtual void replaceWindowDataWith(CWindow* from, CWindow* to);
|
||||||
|
virtual Vector2D predictSizeForNewWindow();
|
||||||
|
|
||||||
virtual void onEnable();
|
virtual void onEnable();
|
||||||
virtual void onDisable();
|
virtual void onDisable();
|
||||||
|
@ -79,9 +80,11 @@ class CHyprDwindleLayout : public IHyprLayout {
|
||||||
void applyNodeDataToWindow(SDwindleNodeData*, bool force = false);
|
void applyNodeDataToWindow(SDwindleNodeData*, bool force = false);
|
||||||
SDwindleNodeData* getNodeFromWindow(CWindow*);
|
SDwindleNodeData* getNodeFromWindow(CWindow*);
|
||||||
SDwindleNodeData* getFirstNodeOnWorkspace(const int&);
|
SDwindleNodeData* getFirstNodeOnWorkspace(const int&);
|
||||||
|
SDwindleNodeData* getClosestNodeOnWorkspace(const int&, const Vector2D&);
|
||||||
SDwindleNodeData* getMasterNodeOnWorkspace(const int&);
|
SDwindleNodeData* getMasterNodeOnWorkspace(const int&);
|
||||||
|
|
||||||
void toggleSplit(CWindow*);
|
void toggleSplit(CWindow*);
|
||||||
|
void swapSplit(CWindow*);
|
||||||
|
|
||||||
eDirection overrideDirection = DIRECTION_DEFAULT;
|
eDirection overrideDirection = DIRECTION_DEFAULT;
|
||||||
|
|
||||||
|
|
|
@ -87,7 +87,7 @@ void IHyprLayout::onWindowCreatedFloating(CWindow* pWindow) {
|
||||||
desiredGeometry.y = xy.y;
|
desiredGeometry.y = xy.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
static auto* const PXWLFORCESCALEZERO = &g_pConfigManager->getConfigValuePtr("xwayland:force_zero_scaling")->intValue;
|
static auto* const PXWLFORCESCALEZERO = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("xwayland:force_zero_scaling");
|
||||||
|
|
||||||
if (!PMONITOR) {
|
if (!PMONITOR) {
|
||||||
Debug::log(ERR, "{:m} has an invalid monitor in onWindowCreatedFloating!!!", pWindow);
|
Debug::log(ERR, "{:m} has an invalid monitor in onWindowCreatedFloating!!!", pWindow);
|
||||||
|
@ -105,7 +105,7 @@ void IHyprLayout::onWindowCreatedFloating(CWindow* pWindow) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// reject any windows with size <= 5x5
|
// reject any windows with size <= 5x5
|
||||||
if (pWindow->m_vRealSize.goalv().x <= 5 || pWindow->m_vRealSize.goalv().y <= 5)
|
if (pWindow->m_vRealSize.goal().x <= 5 || pWindow->m_vRealSize.goal().y <= 5)
|
||||||
pWindow->m_vRealSize = PMONITOR->vecSize / 2.f;
|
pWindow->m_vRealSize = PMONITOR->vecSize / 2.f;
|
||||||
|
|
||||||
if (pWindow->m_bIsX11 && pWindow->m_uSurface.xwayland->override_redirect) {
|
if (pWindow->m_bIsX11 && pWindow->m_uSurface.xwayland->override_redirect) {
|
||||||
|
@ -113,11 +113,11 @@ void IHyprLayout::onWindowCreatedFloating(CWindow* pWindow) {
|
||||||
if (pWindow->m_uSurface.xwayland->x != 0 && pWindow->m_uSurface.xwayland->y != 0)
|
if (pWindow->m_uSurface.xwayland->x != 0 && pWindow->m_uSurface.xwayland->y != 0)
|
||||||
pWindow->m_vRealPosition = g_pXWaylandManager->xwaylandToWaylandCoords({pWindow->m_uSurface.xwayland->x, pWindow->m_uSurface.xwayland->y});
|
pWindow->m_vRealPosition = g_pXWaylandManager->xwaylandToWaylandCoords({pWindow->m_uSurface.xwayland->x, pWindow->m_uSurface.xwayland->y});
|
||||||
else
|
else
|
||||||
pWindow->m_vRealPosition = Vector2D(PMONITOR->vecPosition.x + (PMONITOR->vecSize.x - pWindow->m_vRealSize.goalv().x) / 2.f,
|
pWindow->m_vRealPosition = Vector2D(PMONITOR->vecPosition.x + (PMONITOR->vecSize.x - pWindow->m_vRealSize.goal().x) / 2.f,
|
||||||
PMONITOR->vecPosition.y + (PMONITOR->vecSize.y - pWindow->m_vRealSize.goalv().y) / 2.f);
|
PMONITOR->vecPosition.y + (PMONITOR->vecSize.y - pWindow->m_vRealSize.goal().y) / 2.f);
|
||||||
} else {
|
} else {
|
||||||
pWindow->m_vRealPosition = Vector2D(PMONITOR->vecPosition.x + (PMONITOR->vecSize.x - pWindow->m_vRealSize.goalv().x) / 2.f,
|
pWindow->m_vRealPosition = Vector2D(PMONITOR->vecPosition.x + (PMONITOR->vecSize.x - pWindow->m_vRealSize.goal().x) / 2.f,
|
||||||
PMONITOR->vecPosition.y + (PMONITOR->vecSize.y - pWindow->m_vRealSize.goalv().y) / 2.f);
|
PMONITOR->vecPosition.y + (PMONITOR->vecSize.y - pWindow->m_vRealSize.goal().y) / 2.f);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// we respect the size.
|
// we respect the size.
|
||||||
|
@ -151,8 +151,8 @@ void IHyprLayout::onWindowCreatedFloating(CWindow* pWindow) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*PXWLFORCESCALEZERO && pWindow->m_bIsX11)
|
if (**PXWLFORCESCALEZERO && pWindow->m_bIsX11)
|
||||||
pWindow->m_vRealSize = pWindow->m_vRealSize.goalv() / PMONITOR->scale;
|
pWindow->m_vRealSize = pWindow->m_vRealSize.goal() / PMONITOR->scale;
|
||||||
|
|
||||||
if (pWindow->m_bX11DoesntWantBorders || (pWindow->m_bIsX11 && pWindow->m_uSurface.xwayland->override_redirect)) {
|
if (pWindow->m_bX11DoesntWantBorders || (pWindow->m_bIsX11 && pWindow->m_uSurface.xwayland->override_redirect)) {
|
||||||
pWindow->m_vRealPosition.warp();
|
pWindow->m_vRealPosition.warp();
|
||||||
|
@ -160,11 +160,11 @@ void IHyprLayout::onWindowCreatedFloating(CWindow* pWindow) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pWindow->m_iX11Type != 2) {
|
if (pWindow->m_iX11Type != 2) {
|
||||||
g_pXWaylandManager->setWindowSize(pWindow, pWindow->m_vRealSize.goalv());
|
g_pXWaylandManager->setWindowSize(pWindow, pWindow->m_vRealSize.goal());
|
||||||
|
|
||||||
g_pCompositor->changeWindowZOrder(pWindow, true);
|
g_pCompositor->changeWindowZOrder(pWindow, true);
|
||||||
} else {
|
} else {
|
||||||
pWindow->m_vPendingReportedSize = pWindow->m_vRealSize.goalv();
|
pWindow->m_vPendingReportedSize = pWindow->m_vRealSize.goal();
|
||||||
pWindow->m_vReportedSize = pWindow->m_vPendingReportedSize;
|
pWindow->m_vReportedSize = pWindow->m_vPendingReportedSize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -200,18 +200,18 @@ void IHyprLayout::onBeginDragWindow() {
|
||||||
|
|
||||||
if (!DRAGGINGWINDOW->m_bIsFloating) {
|
if (!DRAGGINGWINDOW->m_bIsFloating) {
|
||||||
if (g_pInputManager->dragMode == MBIND_MOVE) {
|
if (g_pInputManager->dragMode == MBIND_MOVE) {
|
||||||
DRAGGINGWINDOW->m_vLastFloatingSize = (DRAGGINGWINDOW->m_vRealSize.goalv() * 0.8489).clamp(Vector2D{5, 5}, Vector2D{}).floor();
|
DRAGGINGWINDOW->m_vLastFloatingSize = (DRAGGINGWINDOW->m_vRealSize.goal() * 0.8489).clamp(Vector2D{5, 5}, Vector2D{}).floor();
|
||||||
changeWindowFloatingMode(DRAGGINGWINDOW);
|
changeWindowFloatingMode(DRAGGINGWINDOW);
|
||||||
DRAGGINGWINDOW->m_bIsFloating = true;
|
DRAGGINGWINDOW->m_bIsFloating = true;
|
||||||
DRAGGINGWINDOW->m_bDraggingTiled = true;
|
DRAGGINGWINDOW->m_bDraggingTiled = true;
|
||||||
|
|
||||||
DRAGGINGWINDOW->m_vRealPosition = g_pInputManager->getMouseCoordsInternal() - DRAGGINGWINDOW->m_vRealSize.goalv() / 2.f;
|
DRAGGINGWINDOW->m_vRealPosition = g_pInputManager->getMouseCoordsInternal() - DRAGGINGWINDOW->m_vRealSize.goal() / 2.f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_vBeginDragXY = g_pInputManager->getMouseCoordsInternal();
|
m_vBeginDragXY = g_pInputManager->getMouseCoordsInternal();
|
||||||
m_vBeginDragPositionXY = DRAGGINGWINDOW->m_vRealPosition.goalv();
|
m_vBeginDragPositionXY = DRAGGINGWINDOW->m_vRealPosition.goal();
|
||||||
m_vBeginDragSizeXY = DRAGGINGWINDOW->m_vRealSize.goalv();
|
m_vBeginDragSizeXY = DRAGGINGWINDOW->m_vRealSize.goal();
|
||||||
m_vLastDragXY = m_vBeginDragXY;
|
m_vLastDragXY = m_vBeginDragXY;
|
||||||
|
|
||||||
// get the grab corner
|
// get the grab corner
|
||||||
|
@ -268,15 +268,15 @@ void IHyprLayout::onEndDragWindow() {
|
||||||
} else if (g_pInputManager->dragMode == MBIND_MOVE) {
|
} else if (g_pInputManager->dragMode == MBIND_MOVE) {
|
||||||
g_pHyprRenderer->damageWindow(DRAGGINGWINDOW);
|
g_pHyprRenderer->damageWindow(DRAGGINGWINDOW);
|
||||||
const auto MOUSECOORDS = g_pInputManager->getMouseCoordsInternal();
|
const auto MOUSECOORDS = g_pInputManager->getMouseCoordsInternal();
|
||||||
CWindow* pWindow = g_pCompositor->vectorToWindowIdeal(MOUSECOORDS, DRAGGINGWINDOW);
|
CWindow* pWindow = g_pCompositor->vectorToWindowUnified(MOUSECOORDS, RESERVED_EXTENTS | INPUT_EXTENTS | ALLOW_FLOATING | FLOATING_ONLY, DRAGGINGWINDOW);
|
||||||
|
|
||||||
if (pWindow && pWindow->m_bIsFloating) {
|
if (pWindow) {
|
||||||
if (pWindow->checkInputOnDecos(INPUT_TYPE_DRAG_END, MOUSECOORDS, DRAGGINGWINDOW))
|
if (pWindow->checkInputOnDecos(INPUT_TYPE_DRAG_END, MOUSECOORDS, DRAGGINGWINDOW))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (pWindow->m_sGroupData.pNextWindow && DRAGGINGWINDOW->canBeGroupedInto(pWindow)) {
|
if (pWindow->m_sGroupData.pNextWindow && DRAGGINGWINDOW->canBeGroupedInto(pWindow)) {
|
||||||
static const auto* USECURRPOS = &g_pConfigManager->getConfigValuePtr("group:insert_after_current")->intValue;
|
static const auto* USECURRPOS = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("group:insert_after_current");
|
||||||
(*USECURRPOS ? pWindow : pWindow->getGroupTail())->insertWindowToGroup(DRAGGINGWINDOW);
|
(**USECURRPOS ? pWindow : pWindow->getGroupTail())->insertWindowToGroup(DRAGGINGWINDOW);
|
||||||
pWindow->setGroupCurrent(DRAGGINGWINDOW);
|
pWindow->setGroupCurrent(DRAGGINGWINDOW);
|
||||||
DRAGGINGWINDOW->updateWindowDecos();
|
DRAGGINGWINDOW->updateWindowDecos();
|
||||||
|
|
||||||
|
@ -309,13 +309,12 @@ void IHyprLayout::onMouseMove(const Vector2D& mousePos) {
|
||||||
const auto DELTA = Vector2D(mousePos.x - m_vBeginDragXY.x, mousePos.y - m_vBeginDragXY.y);
|
const auto DELTA = Vector2D(mousePos.x - m_vBeginDragXY.x, mousePos.y - m_vBeginDragXY.y);
|
||||||
const auto TICKDELTA = Vector2D(mousePos.x - m_vLastDragXY.x, mousePos.y - m_vLastDragXY.y);
|
const auto TICKDELTA = Vector2D(mousePos.x - m_vLastDragXY.x, mousePos.y - m_vLastDragXY.y);
|
||||||
|
|
||||||
static auto* const PANIMATEMOUSE = &g_pConfigManager->getConfigValuePtr("misc:animate_mouse_windowdragging")->intValue;
|
static auto* const PANIMATEMOUSE = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("misc:animate_mouse_windowdragging");
|
||||||
static auto* const PANIMATE = &g_pConfigManager->getConfigValuePtr("misc:animate_manual_resizes")->intValue;
|
static auto* const PANIMATE = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("misc:animate_manual_resizes");
|
||||||
|
|
||||||
if ((abs(TICKDELTA.x) < 1.f && abs(TICKDELTA.y) < 1.f) ||
|
if ((abs(TICKDELTA.x) < 1.f && abs(TICKDELTA.y) < 1.f) ||
|
||||||
(std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - TIMER).count() <
|
(std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - TIMER).count() <
|
||||||
1000.0 / g_pHyprRenderer->m_pMostHzMonitor->refreshRate &&
|
1000.0 / g_pHyprRenderer->m_pMostHzMonitor->refreshRate))
|
||||||
(*PANIMATEMOUSE || *PANIMATE)))
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
TIMER = std::chrono::high_resolution_clock::now();
|
TIMER = std::chrono::high_resolution_clock::now();
|
||||||
|
@ -326,15 +325,15 @@ void IHyprLayout::onMouseMove(const Vector2D& mousePos) {
|
||||||
|
|
||||||
if (g_pInputManager->dragMode == MBIND_MOVE) {
|
if (g_pInputManager->dragMode == MBIND_MOVE) {
|
||||||
|
|
||||||
CBox wb = {m_vBeginDragPositionXY + DELTA, DRAGGINGWINDOW->m_vRealSize.goalv()};
|
CBox wb = {m_vBeginDragPositionXY + DELTA, DRAGGINGWINDOW->m_vRealSize.goal()};
|
||||||
wb.round();
|
wb.round();
|
||||||
|
|
||||||
if (*PANIMATEMOUSE)
|
if (**PANIMATEMOUSE)
|
||||||
DRAGGINGWINDOW->m_vRealPosition = wb.pos();
|
DRAGGINGWINDOW->m_vRealPosition = wb.pos();
|
||||||
else
|
else
|
||||||
DRAGGINGWINDOW->m_vRealPosition.setValueAndWarp(wb.pos());
|
DRAGGINGWINDOW->m_vRealPosition.setValueAndWarp(wb.pos());
|
||||||
|
|
||||||
g_pXWaylandManager->setWindowSize(DRAGGINGWINDOW, DRAGGINGWINDOW->m_vRealSize.goalv());
|
g_pXWaylandManager->setWindowSize(DRAGGINGWINDOW, DRAGGINGWINDOW->m_vRealSize.goal());
|
||||||
} else if (g_pInputManager->dragMode == MBIND_RESIZE || g_pInputManager->dragMode == MBIND_RESIZE_FORCE_RATIO || g_pInputManager->dragMode == MBIND_RESIZE_BLOCK_RATIO) {
|
} else if (g_pInputManager->dragMode == MBIND_RESIZE || g_pInputManager->dragMode == MBIND_RESIZE_FORCE_RATIO || g_pInputManager->dragMode == MBIND_RESIZE_BLOCK_RATIO) {
|
||||||
if (DRAGGINGWINDOW->m_bIsFloating) {
|
if (DRAGGINGWINDOW->m_bIsFloating) {
|
||||||
|
|
||||||
|
@ -387,7 +386,7 @@ void IHyprLayout::onMouseMove(const Vector2D& mousePos) {
|
||||||
CBox wb = {newPos, newSize};
|
CBox wb = {newPos, newSize};
|
||||||
wb.round();
|
wb.round();
|
||||||
|
|
||||||
if (*PANIMATE) {
|
if (**PANIMATE) {
|
||||||
DRAGGINGWINDOW->m_vRealSize = wb.size();
|
DRAGGINGWINDOW->m_vRealSize = wb.size();
|
||||||
DRAGGINGWINDOW->m_vRealPosition = wb.pos();
|
DRAGGINGWINDOW->m_vRealPosition = wb.pos();
|
||||||
} else {
|
} else {
|
||||||
|
@ -395,14 +394,14 @@ void IHyprLayout::onMouseMove(const Vector2D& mousePos) {
|
||||||
DRAGGINGWINDOW->m_vRealPosition.setValueAndWarp(wb.pos());
|
DRAGGINGWINDOW->m_vRealPosition.setValueAndWarp(wb.pos());
|
||||||
}
|
}
|
||||||
|
|
||||||
g_pXWaylandManager->setWindowSize(DRAGGINGWINDOW, DRAGGINGWINDOW->m_vRealSize.goalv());
|
g_pXWaylandManager->setWindowSize(DRAGGINGWINDOW, DRAGGINGWINDOW->m_vRealSize.goal());
|
||||||
} else {
|
} else {
|
||||||
resizeActiveWindow(TICKDELTA, m_eGrabbedCorner, DRAGGINGWINDOW);
|
resizeActiveWindow(TICKDELTA, m_eGrabbedCorner, DRAGGINGWINDOW);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// get middle point
|
// get middle point
|
||||||
Vector2D middle = DRAGGINGWINDOW->m_vRealPosition.vec() + DRAGGINGWINDOW->m_vRealSize.vec() / 2.f;
|
Vector2D middle = DRAGGINGWINDOW->m_vRealPosition.value() + DRAGGINGWINDOW->m_vRealSize.value() / 2.f;
|
||||||
|
|
||||||
// and check its monitor
|
// and check its monitor
|
||||||
const auto PMONITOR = g_pCompositor->getMonitorFromVector(middle);
|
const auto PMONITOR = g_pCompositor->getMonitorFromVector(middle);
|
||||||
|
@ -436,18 +435,18 @@ void IHyprLayout::changeWindowFloatingMode(CWindow* pWindow) {
|
||||||
EMIT_HOOK_EVENT("changeFloatingMode", pWindow);
|
EMIT_HOOK_EVENT("changeFloatingMode", pWindow);
|
||||||
|
|
||||||
if (!TILED) {
|
if (!TILED) {
|
||||||
const auto PNEWMON = g_pCompositor->getMonitorFromVector(pWindow->m_vRealPosition.vec() + pWindow->m_vRealSize.vec() / 2.f);
|
const auto PNEWMON = g_pCompositor->getMonitorFromVector(pWindow->m_vRealPosition.value() + pWindow->m_vRealSize.value() / 2.f);
|
||||||
pWindow->m_iMonitorID = PNEWMON->ID;
|
pWindow->m_iMonitorID = PNEWMON->ID;
|
||||||
pWindow->moveToWorkspace(PNEWMON->specialWorkspaceID != 0 ? PNEWMON->specialWorkspaceID : PNEWMON->activeWorkspace);
|
pWindow->moveToWorkspace(PNEWMON->specialWorkspaceID != 0 ? PNEWMON->specialWorkspaceID : PNEWMON->activeWorkspace);
|
||||||
pWindow->updateGroupOutputs();
|
pWindow->updateGroupOutputs();
|
||||||
|
|
||||||
// save real pos cuz the func applies the default 5,5 mid
|
// save real pos cuz the func applies the default 5,5 mid
|
||||||
const auto PSAVEDPOS = pWindow->m_vRealPosition.goalv();
|
const auto PSAVEDPOS = pWindow->m_vRealPosition.goal();
|
||||||
const auto PSAVEDSIZE = pWindow->m_vRealSize.goalv();
|
const auto PSAVEDSIZE = pWindow->m_vRealSize.goal();
|
||||||
|
|
||||||
// if the window is pseudo, update its size
|
// if the window is pseudo, update its size
|
||||||
if (!pWindow->m_bDraggingTiled)
|
if (!pWindow->m_bDraggingTiled)
|
||||||
pWindow->m_vPseudoSize = pWindow->m_vRealSize.goalv();
|
pWindow->m_vPseudoSize = pWindow->m_vRealSize.goal();
|
||||||
|
|
||||||
pWindow->m_vLastFloatingSize = PSAVEDSIZE;
|
pWindow->m_vLastFloatingSize = PSAVEDSIZE;
|
||||||
|
|
||||||
|
@ -469,16 +468,19 @@ void IHyprLayout::changeWindowFloatingMode(CWindow* pWindow) {
|
||||||
|
|
||||||
g_pCompositor->changeWindowZOrder(pWindow, true);
|
g_pCompositor->changeWindowZOrder(pWindow, true);
|
||||||
|
|
||||||
if (DELTALESSTHAN(pWindow->m_vRealSize.vec().x, pWindow->m_vLastFloatingSize.x, 10) && DELTALESSTHAN(pWindow->m_vRealSize.vec().y, pWindow->m_vLastFloatingSize.y, 10)) {
|
CBox wb = {pWindow->m_vRealPosition.goal() + (pWindow->m_vRealSize.goal() - pWindow->m_vLastFloatingSize) / 2.f, pWindow->m_vLastFloatingSize};
|
||||||
pWindow->m_vRealPosition = pWindow->m_vRealPosition.goalv() + (pWindow->m_vRealSize.goalv() - pWindow->m_vLastFloatingSize) / 2.f + Vector2D{10, 10};
|
wb.round();
|
||||||
pWindow->m_vRealSize = pWindow->m_vLastFloatingSize - Vector2D{20, 20};
|
|
||||||
|
if (DELTALESSTHAN(pWindow->m_vRealSize.value().x, pWindow->m_vLastFloatingSize.x, 10) &&
|
||||||
|
DELTALESSTHAN(pWindow->m_vRealSize.value().y, pWindow->m_vLastFloatingSize.y, 10)) {
|
||||||
|
wb = {wb.pos() + Vector2D{10, 10}, wb.size() - Vector2D{20, 20}};
|
||||||
}
|
}
|
||||||
|
|
||||||
pWindow->m_vRealPosition = pWindow->m_vRealPosition.goalv() + (pWindow->m_vRealSize.goalv() - pWindow->m_vLastFloatingSize) / 2.f;
|
pWindow->m_vRealPosition = wb.pos();
|
||||||
pWindow->m_vRealSize = pWindow->m_vLastFloatingSize;
|
pWindow->m_vRealSize = wb.size();
|
||||||
|
|
||||||
pWindow->m_vSize = pWindow->m_vRealSize.goalv();
|
pWindow->m_vSize = wb.pos();
|
||||||
pWindow->m_vPosition = pWindow->m_vRealPosition.goalv();
|
pWindow->m_vPosition = wb.size();
|
||||||
|
|
||||||
g_pHyprRenderer->damageMonitor(g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID));
|
g_pHyprRenderer->damageMonitor(g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID));
|
||||||
|
|
||||||
|
@ -504,7 +506,7 @@ void IHyprLayout::moveActiveWindow(const Vector2D& delta, CWindow* pWindow) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
PWINDOW->m_vRealPosition = PWINDOW->m_vRealPosition.goalv() + delta;
|
PWINDOW->m_vRealPosition = PWINDOW->m_vRealPosition.goal() + delta;
|
||||||
|
|
||||||
g_pHyprRenderer->damageWindow(PWINDOW);
|
g_pHyprRenderer->damageWindow(PWINDOW);
|
||||||
}
|
}
|
||||||
|
@ -529,7 +531,7 @@ CWindow* IHyprLayout::getNextWindowCandidate(CWindow* pWindow) {
|
||||||
// find whether there is a floating window below this one
|
// find whether there is a floating window below this one
|
||||||
for (auto& w : g_pCompositor->m_vWindows) {
|
for (auto& w : g_pCompositor->m_vWindows) {
|
||||||
if (w->m_bIsMapped && !w->isHidden() && w->m_bIsFloating && w->m_iX11Type != 2 && w->m_iWorkspaceID == pWindow->m_iWorkspaceID && !w->m_bX11ShouldntFocus &&
|
if (w->m_bIsMapped && !w->isHidden() && w->m_bIsFloating && w->m_iX11Type != 2 && w->m_iWorkspaceID == pWindow->m_iWorkspaceID && !w->m_bX11ShouldntFocus &&
|
||||||
!w->m_bNoFocus && w.get() != pWindow) {
|
!w->m_sAdditionalConfigData.noFocus && w.get() != pWindow) {
|
||||||
if (VECINRECT((pWindow->m_vSize / 2.f + pWindow->m_vPosition), w->m_vPosition.x, w->m_vPosition.y, w->m_vPosition.x + w->m_vSize.x,
|
if (VECINRECT((pWindow->m_vSize / 2.f + pWindow->m_vPosition), w->m_vPosition.x, w->m_vPosition.y, w->m_vPosition.x + w->m_vSize.x,
|
||||||
w->m_vPosition.y + w->m_vSize.y)) {
|
w->m_vPosition.y + w->m_vSize.y)) {
|
||||||
return w.get();
|
return w.get();
|
||||||
|
@ -542,13 +544,14 @@ CWindow* IHyprLayout::getNextWindowCandidate(CWindow* pWindow) {
|
||||||
return m_pLastTiledWindow;
|
return m_pLastTiledWindow;
|
||||||
|
|
||||||
// if we don't, let's try to find any window that is in the middle
|
// if we don't, let's try to find any window that is in the middle
|
||||||
if (const auto PWINDOWCANDIDATE = g_pCompositor->vectorToWindowIdeal(pWindow->middle()); PWINDOWCANDIDATE && PWINDOWCANDIDATE != pWindow)
|
if (const auto PWINDOWCANDIDATE = g_pCompositor->vectorToWindowUnified(pWindow->middle(), RESERVED_EXTENTS | INPUT_EXTENTS | ALLOW_FLOATING);
|
||||||
|
PWINDOWCANDIDATE && PWINDOWCANDIDATE != pWindow)
|
||||||
return PWINDOWCANDIDATE;
|
return PWINDOWCANDIDATE;
|
||||||
|
|
||||||
// if not, floating window
|
// if not, floating window
|
||||||
for (auto& w : g_pCompositor->m_vWindows) {
|
for (auto& w : g_pCompositor->m_vWindows) {
|
||||||
if (w->m_bIsMapped && !w->isHidden() && w->m_bIsFloating && w->m_iX11Type != 2 && w->m_iWorkspaceID == pWindow->m_iWorkspaceID && !w->m_bX11ShouldntFocus &&
|
if (w->m_bIsMapped && !w->isHidden() && w->m_bIsFloating && w->m_iX11Type != 2 && w->m_iWorkspaceID == pWindow->m_iWorkspaceID && !w->m_bX11ShouldntFocus &&
|
||||||
!w->m_bNoFocus && w.get() != pWindow)
|
!w->m_sAdditionalConfigData.noFocus && w.get() != pWindow)
|
||||||
return w.get();
|
return w.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -557,7 +560,7 @@ CWindow* IHyprLayout::getNextWindowCandidate(CWindow* pWindow) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// if it was a tiled window, we first try to find the window that will replace it.
|
// if it was a tiled window, we first try to find the window that will replace it.
|
||||||
auto pWindowCandidate = g_pCompositor->vectorToWindowIdeal(pWindow->middle());
|
auto pWindowCandidate = g_pCompositor->vectorToWindowUnified(pWindow->middle(), RESERVED_EXTENTS | INPUT_EXTENTS | ALLOW_FLOATING);
|
||||||
|
|
||||||
if (!pWindowCandidate)
|
if (!pWindowCandidate)
|
||||||
pWindowCandidate = g_pCompositor->getTopLeftWindowOnWorkspace(pWindow->m_iWorkspaceID);
|
pWindowCandidate = g_pCompositor->getTopLeftWindowOnWorkspace(pWindow->m_iWorkspaceID);
|
||||||
|
@ -591,4 +594,8 @@ void IHyprLayout::requestFocusForWindow(CWindow* pWindow) {
|
||||||
g_pCompositor->focusWindow(pWindow);
|
g_pCompositor->focusWindow(pWindow);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Vector2D IHyprLayout::predictSizeForNewWindow() {
|
||||||
|
return Vector2D{};
|
||||||
|
}
|
||||||
|
|
||||||
IHyprLayout::~IHyprLayout() {}
|
IHyprLayout::~IHyprLayout() {}
|
||||||
|
|
|
@ -181,6 +181,12 @@ class IHyprLayout {
|
||||||
*/
|
*/
|
||||||
virtual void requestFocusForWindow(CWindow*);
|
virtual void requestFocusForWindow(CWindow*);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Called to predict the size of a newly opened window to send it a configure.
|
||||||
|
Return 0,0 if unpredictable
|
||||||
|
*/
|
||||||
|
virtual Vector2D predictSizeForNewWindow();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Vector2D m_vBeginDragXY;
|
Vector2D m_vBeginDragXY;
|
||||||
Vector2D m_vLastDragXY;
|
Vector2D m_vLastDragXY;
|
||||||
|
|