upstream
17
.github/ISSUE_TEMPLATE/bug.yml
vendored
|
@ -9,12 +9,23 @@ body:
|
|||
|
||||
---
|
||||
|
||||
- type: input
|
||||
- type: textarea
|
||||
id: ver
|
||||
attributes:
|
||||
label: Hyprland Version
|
||||
description: "Paste here the output of `hyprctl version`."
|
||||
placeholder: Hyprland, built from branch main at commit...
|
||||
description: "Paste here the output of `hyprctl version`. For hyprland after 0.34.0, paste `hyprctl systeminfo` instead."
|
||||
value: "<details>
|
||||
<summary>System/Version info</summary>
|
||||
|
||||
|
||||
```sh
|
||||
|
||||
<Paste the output of the command here>
|
||||
|
||||
```
|
||||
|
||||
|
||||
</details>"
|
||||
validations:
|
||||
required: true
|
||||
|
||||
|
|
1
.github/actions/setup_base/action.yml
vendored
|
@ -23,6 +23,7 @@ runs:
|
|||
glm \
|
||||
glslang \
|
||||
go \
|
||||
hyprlang \
|
||||
jq \
|
||||
libc++ \
|
||||
libdisplay-info \
|
||||
|
|
102
.github/workflows/ci.yaml
vendored
|
@ -8,29 +8,20 @@ jobs:
|
|||
container:
|
||||
image: archlinux
|
||||
steps:
|
||||
- name: Get required pacman pkgs
|
||||
run: |
|
||||
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
|
||||
- name: Checkout repository actions
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
sparse-checkout: .github/actions
|
||||
|
||||
- name: Setup base
|
||||
uses: ./.github/actions/setup_base
|
||||
with:
|
||||
INSTALL_XORG_PKGS: true
|
||||
|
||||
- name: Build Hyprland
|
||||
run: |
|
||||
git submodule sync --recursive && git submodule update --init --force --recursive
|
||||
make all
|
||||
|
||||
- name: Compress and package artifacts
|
||||
run: |
|
||||
mkdir x86_64-pc-linux-gnu
|
||||
|
@ -45,6 +36,7 @@ jobs:
|
|||
cp -r example/ hyprland/
|
||||
cp -r assets/ hyprland/
|
||||
tar -cvf Hyprland.tar.xz hyprland
|
||||
|
||||
- name: Release
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
|
@ -57,28 +49,19 @@ jobs:
|
|||
container:
|
||||
image: archlinux
|
||||
steps:
|
||||
- name: Download dependencies
|
||||
run: |
|
||||
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
|
||||
- name: Checkout repository actions
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true
|
||||
sparse-checkout: .github/actions
|
||||
|
||||
- name: Setup base
|
||||
uses: ./.github/actions/setup_base
|
||||
|
||||
- name: Configure
|
||||
run: |
|
||||
meson obj-x86_64-pc-linux-gnu \
|
||||
-Ddefault_library=static
|
||||
run: meson setup build -Ddefault_library=static
|
||||
|
||||
- name: Compile
|
||||
run: ninja -C obj-x86_64-pc-linux-gnu
|
||||
run: ninja -C build
|
||||
|
||||
noxwayland:
|
||||
name: "Build Hyprland in pure Wayland (Arch)"
|
||||
|
@ -86,23 +69,36 @@ jobs:
|
|||
container:
|
||||
image: archlinux
|
||||
steps:
|
||||
- name: Download dependencies
|
||||
run: |
|
||||
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
|
||||
- name: Checkout repository actions
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true
|
||||
sparse-checkout: .github/actions
|
||||
|
||||
- name: Setup base
|
||||
uses: ./.github/actions/setup_base
|
||||
|
||||
- name: Configure
|
||||
run: mkdir -p build && cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DNO_XWAYLAND:STRING=true -H./ -B./build -G Ninja
|
||||
|
||||
- name: Compile
|
||||
run: make release
|
||||
|
||||
clang-format:
|
||||
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
|
||||
authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
|
||||
|
||||
- run: nix build -L ${{ matrix.command }}
|
||||
- run: nix build .#${{ matrix.package }} -L
|
||||
|
|
23
.github/workflows/security-checks.yml
vendored
|
@ -42,32 +42,23 @@ jobs:
|
|||
language: [ 'cpp' ]
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
- name: Checkout repository actions
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
sparse-checkout: .github/actions
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v2
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
|
||||
- name: Init Hyprland build
|
||||
run: |
|
||||
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
|
||||
- name: Setup base
|
||||
uses: ./.github/actions/setup_base
|
||||
with:
|
||||
submodules: recursive
|
||||
INSTALL_XORG_PKGS: true
|
||||
|
||||
- name: Build Hyprland
|
||||
run: |
|
||||
git submodule sync --recursive && git submodule update --init --force --recursive
|
||||
make all
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
|
|
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
|
||||
|
||||
src/version.h
|
||||
|
||||
.direnv
|
||||
|
|
3
.gitmodules
vendored
|
@ -1,7 +1,6 @@
|
|||
[submodule "wlroots"]
|
||||
path = subprojects/wlroots
|
||||
url = https://github.com/DRAGONTOS/wlroots.git
|
||||
branch = 0.18.0-dev
|
||||
url = https://gitlab.freedesktop.org/wlroots/wlroots.git
|
||||
[submodule "subprojects/hyprland-protocols"]
|
||||
path = subprojects/hyprland-protocols
|
||||
url = https://github.com/hyprwm/hyprland-protocols
|
||||
|
|
|
@ -57,8 +57,8 @@ ExternalProject_Add(
|
|||
wlroots
|
||||
PREFIX ${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
|
||||
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
|
||||
PATCH_COMMAND sed -E -i -e "s/(soversion = .*$)/soversion = 13032/g" meson.build
|
||||
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_ALWAYS true
|
||||
BUILD_IN_SOURCE true
|
||||
|
@ -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) # 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")
|
||||
|
||||
|
|
33
Makefile
|
@ -1,22 +1,22 @@
|
|||
PREFIX = /usr/local
|
||||
|
||||
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`
|
||||
chmod -R 777 ./build
|
||||
|
||||
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`
|
||||
chmod -R 777 ./build
|
||||
|
||||
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`
|
||||
chmod -R 777 ./build
|
||||
|
||||
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`
|
||||
chmod -R 777 ./build
|
||||
|
||||
|
@ -42,10 +42,10 @@ install:
|
|||
chmod 755 ${PREFIX}/bin/Hyprland
|
||||
chmod 755 ${PREFIX}/bin/hyprctl
|
||||
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
|
||||
mkdir -p ${PREFIX}/share/hyprland
|
||||
cp ./assets/wall_* ${PREFIX}/share/hyprland
|
||||
cp ./assets/wall* ${PREFIX}/share/hyprland
|
||||
mkdir -p ${PREFIX}/share/xdg-desktop-portal
|
||||
cp ./assets/hyprland-portals.conf ${PREFIX}/share/xdg-desktop-portal
|
||||
|
||||
|
@ -106,3 +106,24 @@ man:
|
|||
--variable=section:1 \
|
||||
--from rst \
|
||||
--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
|
||||
- Custom bezier curves for the best animations
|
||||
- Powerful plugin support
|
||||
- Built-in plugin manager
|
||||
- Tearing support for better gaming performance
|
||||
- Easily expandable and readable codebase
|
||||
- Fast and active development
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
wallpaper_types = ['', 'anime_', 'anime2_']
|
||||
wallpapers = ['0', '1', '2']
|
||||
|
||||
foreach type : wallpaper_types
|
||||
foreach size : [2, 4, 8]
|
||||
install_data(f'wall_@type@@size@K.png', install_dir: join_paths(get_option('datadir'), 'hyprland'), install_tag: 'runtime')
|
||||
endforeach
|
||||
foreach type : wallpapers
|
||||
install_data(f'wall@type@.png', install_dir: join_paths(get_option('datadir'), 'hyprland'), install_tag: 'runtime')
|
||||
endforeach
|
||||
|
||||
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)
|
||||
|
||||
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.
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
# Execute your favorite apps at launch
|
||||
# exec-once = waybar & hyprpaper & firefox
|
||||
|
||||
# Source a file (multi-file configs)
|
||||
# source = ~/.config/hypr/myColors.conf
|
||||
|
||||
# Startup
|
||||
#exec-once = waybar & hyprpaper & dunst
|
||||
exec-once = /usr/libexec/polkit-gnome-authentication-agent-1
|
||||
exec-once = hyprpm reload -n
|
||||
#exec-once = wl-clip-persist --clipboard both
|
||||
#exec-once = wl-paste -p -t text --watch clipman store -P --histpath="~/.local/share/clipman-primary.json"
|
||||
# Set programs that you use
|
||||
$terminal = kitty
|
||||
$fileManager = dolphin
|
||||
$menu = wofi --show drun
|
||||
|
||||
# Plugins
|
||||
#plugin {
|
||||
# split-monitor-workspaces {
|
||||
# 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
|
||||
# }
|
||||
# }
|
||||
#}
|
||||
# Some default env vars.
|
||||
env = XCURSOR_SIZE,24
|
||||
env = QT_QPA_PLATFORMTHEME,qt5ct # change to qt6ct if you have that
|
||||
|
||||
# For all categories, see https://wiki.hyprland.org/Configuring/Variables/
|
||||
input {
|
||||
|
@ -119,7 +39,7 @@ input {
|
|||
follow_mouse = 1
|
||||
|
||||
touchpad {
|
||||
natural_scroll = no
|
||||
natural_scroll = false
|
||||
}
|
||||
|
||||
sensitivity = 0 # -1.0 - 1.0, 0 means no modification.
|
||||
|
@ -130,11 +50,14 @@ general {
|
|||
|
||||
gaps_in = 5
|
||||
gaps_out = 20
|
||||
border_size = 3
|
||||
col.active_border = 0xFF8330DB 0xFF3e136c
|
||||
col.inactive_border = 0xFF4D4D4D 0xFF333333
|
||||
border_size = 2
|
||||
col.active_border = rgba(33ccffee) rgba(00ff99ee) 45deg
|
||||
col.inactive_border = rgba(595959aa)
|
||||
|
||||
layout = dwindle
|
||||
|
||||
# Please see https://wiki.hyprland.org/Configuring/Tearing/ before you turn this on
|
||||
allow_tearing = false
|
||||
}
|
||||
|
||||
decoration {
|
||||
|
@ -144,18 +67,20 @@ decoration {
|
|||
|
||||
blur {
|
||||
enabled = true
|
||||
size = 1.5
|
||||
size = 3
|
||||
passes = 1
|
||||
|
||||
vibrancy = 0.1696
|
||||
}
|
||||
|
||||
drop_shadow = yes
|
||||
drop_shadow = true
|
||||
shadow_range = 4
|
||||
shadow_render_power = 3
|
||||
col.shadow = rgba(1a1a1aee)
|
||||
}
|
||||
|
||||
animations {
|
||||
enabled = yes
|
||||
enabled = true
|
||||
|
||||
# Some default animations, see https://wiki.hyprland.org/Configuring/Animations/ for more
|
||||
|
||||
|
@ -164,14 +89,15 @@ animations {
|
|||
animation = windows, 1, 7, myBezier
|
||||
animation = windowsOut, 1, 7, default, popin 80%
|
||||
animation = border, 1, 10, default
|
||||
animation = borderangle, 1, 8, default
|
||||
animation = fade, 1, 7, default
|
||||
animation = workspaces, 1, 4, default
|
||||
animation = workspaces, 1, 6, default
|
||||
}
|
||||
|
||||
dwindle {
|
||||
# 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
|
||||
preserve_split = yes # you probably want this
|
||||
pseudotile = true # master switch for pseudotiling. Enabling is bound to mainMod + P in the keybinds section below
|
||||
preserve_split = true # you probably want this
|
||||
}
|
||||
|
||||
master {
|
||||
|
@ -181,39 +107,41 @@ master {
|
|||
|
||||
gestures {
|
||||
# See https://wiki.hyprland.org/Configuring/Variables/ for more
|
||||
workspace_swipe = off
|
||||
workspace_swipe = false
|
||||
}
|
||||
|
||||
# unscale XWayland
|
||||
xwayland {
|
||||
force_zero_scaling = true
|
||||
misc {
|
||||
# See https://wiki.hyprland.org/Configuring/Variables/ for more
|
||||
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
|
||||
windowrule = rounding 1,class:^(Wine)$
|
||||
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)
|
||||
windowrulev2 = suppressevent maximize, class:.* # You'll probably like this.
|
||||
|
||||
|
||||
# See https://wiki.hyprland.org/Configuring/Keywords/ for more
|
||||
$mainMod = SUPER
|
||||
|
||||
# Example binds, see https://wiki.hyprland.org/Configuring/Binds/ for more
|
||||
bind = $mainMod, RETURN, exec, $terminal
|
||||
bind = $mainMod, Q, killactive,
|
||||
bind = $mainMod SHIFT, Q, exit,
|
||||
bind = $mainMod, F, fullscreen,
|
||||
bind = $mainMod, SPACE, togglefloating,
|
||||
bind = $mainMod, L, exec, gtklock
|
||||
bind = $mainMod CTRL, B, exec, killall waybar && waybar -c /home/$USER/.config/waybar/config-hypr
|
||||
|
||||
bind = $mainMod, D, exec, rofi -show run
|
||||
bind = $mainMod, Q, exec, $terminal
|
||||
bind = $mainMod, C, killactive,
|
||||
bind = $mainMod, M, exit,
|
||||
bind = $mainMod, E, exec, $fileManager
|
||||
bind = $mainMod, V, togglefloating,
|
||||
bind = $mainMod, R, exec, $menu
|
||||
bind = $mainMod, P, pseudo, # dwindle
|
||||
bind = $mainMod, J, togglesplit, # dwindle
|
||||
bind = $mainMod, Print, exec, grim -g "$(slurp)" - | swappy -f - # take a screenshot
|
||||
|
||||
# Move focus with mainMod + arrow keys
|
||||
bind = $mainMod, left, movefocus, l
|
||||
|
@ -221,12 +149,6 @@ bind = $mainMod, right, movefocus, r
|
|||
bind = $mainMod, up, movefocus, u
|
||||
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]
|
||||
bind = $mainMod, 1, workspace, 1
|
||||
bind = $mainMod, 2, workspace, 2
|
||||
|
@ -251,22 +173,9 @@ bind = $mainMod SHIFT, 8, movetoworkspace, 8
|
|||
bind = $mainMod SHIFT, 9, movetoworkspace, 9
|
||||
bind = $mainMod SHIFT, 0, movetoworkspace, 10
|
||||
|
||||
|
||||
# vm fix
|
||||
bind=CTRL,ALT_L,submap,passthrough
|
||||
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
|
||||
# Example special workspace (scratchpad)
|
||||
bind = $mainMod, S, togglespecialworkspace, magic
|
||||
bind = $mainMod SHIFT, S, movetoworkspace, special:magic
|
||||
|
||||
# Scroll through existing workspaces with mainMod + scroll
|
||||
bind = $mainMod, mouse_down, workspace, e+1
|
||||
|
|
47
flake.lock
generated
|
@ -23,13 +23,36 @@
|
|||
"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": {
|
||||
"locked": {
|
||||
"lastModified": 1703438236,
|
||||
"narHash": "sha256-aqVBq1u09yFhL7bj1/xyUeJjzr92fXVvQSSEx6AdB1M=",
|
||||
"lastModified": 1708807242,
|
||||
"narHash": "sha256-sRTRkhMD4delO/hPxxi+XwLqPn8BuUq6nnj4JqLwOu0=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "5f64a12a728902226210bf01d25ec6cbb9d9265b",
|
||||
"rev": "73de017ef2d18a04ac4bfd0c02650007ccb31c2a",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -42,6 +65,7 @@
|
|||
"root": {
|
||||
"inputs": {
|
||||
"hyprland-protocols": "hyprland-protocols",
|
||||
"hyprlang": "hyprlang",
|
||||
"nixpkgs": "nixpkgs",
|
||||
"systems": "systems",
|
||||
"wlroots": "wlroots",
|
||||
|
@ -67,18 +91,18 @@
|
|||
"flake": false,
|
||||
"locked": {
|
||||
"host": "gitlab.freedesktop.org",
|
||||
"lastModified": 1701368958,
|
||||
"narHash": "sha256-7kvyoA91etzVEl9mkA/EJfB6z/PltxX7Xc4gcr7/xlo=",
|
||||
"lastModified": 1708558866,
|
||||
"narHash": "sha256-Mz6hCtommq7RQfcPnxLINigO4RYSNt23HeJHC6mVmWI=",
|
||||
"owner": "wlroots",
|
||||
"repo": "wlroots",
|
||||
"rev": "5d639394f3e83b01596dcd166a44a9a1a2583350",
|
||||
"rev": "0cb091f1a2d345f37d2ee445f4ffd04f7f4ec9e5",
|
||||
"type": "gitlab"
|
||||
},
|
||||
"original": {
|
||||
"host": "gitlab.freedesktop.org",
|
||||
"owner": "wlroots",
|
||||
"repo": "wlroots",
|
||||
"rev": "5d639394f3e83b01596dcd166a44a9a1a2583350",
|
||||
"rev": "0cb091f1a2d345f37d2ee445f4ffd04f7f4ec9e5",
|
||||
"type": "gitlab"
|
||||
}
|
||||
},
|
||||
|
@ -87,6 +111,9 @@
|
|||
"hyprland-protocols": [
|
||||
"hyprland-protocols"
|
||||
],
|
||||
"hyprlang": [
|
||||
"hyprlang"
|
||||
],
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
],
|
||||
|
@ -95,11 +122,11 @@
|
|||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1703514399,
|
||||
"narHash": "sha256-VRr5Xc4S/VPr/gU3fiOD3vSIL2+GJ+LUrmFTWTwnTz4=",
|
||||
"lastModified": 1708696469,
|
||||
"narHash": "sha256-shh5wmpeYy3MmsBfkm4f76yPsBDGk6OLYRVG+ARy2F0=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "xdg-desktop-portal-hyprland",
|
||||
"rev": "0a318a7a217a6402b0b705837cd5b50b0e94b31b",
|
||||
"rev": "1b713911c2f12b96c2574474686e4027ac4bf826",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
|
10
flake.nix
|
@ -12,7 +12,7 @@
|
|||
host = "gitlab.freedesktop.org";
|
||||
owner = "wlroots";
|
||||
repo = "wlroots";
|
||||
rev = "5d639394f3e83b01596dcd166a44a9a1a2583350";
|
||||
rev = "0cb091f1a2d345f37d2ee445f4ffd04f7f4ec9e5";
|
||||
flake = false;
|
||||
};
|
||||
|
||||
|
@ -22,11 +22,18 @@
|
|||
inputs.systems.follows = "systems";
|
||||
};
|
||||
|
||||
hyprlang = {
|
||||
url = "github:hyprwm/hyprlang";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
inputs.systems.follows = "systems";
|
||||
};
|
||||
|
||||
xdph = {
|
||||
url = "github:hyprwm/xdg-desktop-portal-hyprland";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
inputs.systems.follows = "systems";
|
||||
inputs.hyprland-protocols.follows = "hyprland-protocols";
|
||||
inputs.hyprlang.follows = "hyprlang";
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -86,6 +93,7 @@
|
|||
name = "hyprland-shell";
|
||||
nativeBuildInputs = with pkgsFor.${system}; [cmake python3];
|
||||
buildInputs = [self.packages.${system}.wlroots-hyprland];
|
||||
hardeningDisable = ["fortify"];
|
||||
inputsFrom = [
|
||||
self.packages.${system}.wlroots-hyprland
|
||||
self.packages.${system}.hyprland
|
||||
|
|
132
hyprctl/main.cpp
|
@ -23,49 +23,42 @@
|
|||
#include <filesystem>
|
||||
#include <stdarg.h>
|
||||
|
||||
const std::string USAGE = R"#(usage: hyprctl [flags] [<command> [args]]
|
||||
hyprctl --batch {<command 1> [args] ; <command 2> [args] ; ...}
|
||||
LISTING COMMANDS:
|
||||
monitors: List outputs
|
||||
workspaces: List all workspaces
|
||||
activeworkspace: Get currently active workspace
|
||||
clients: List clients (e.g. windows)
|
||||
activewindow: Get currently active window
|
||||
layers: List layers
|
||||
animations: List animations and bezier curves in use
|
||||
devices: List devices
|
||||
binds: List registered binds
|
||||
instances: List running Hyprland instances
|
||||
layouts: List layouts
|
||||
globalshortcuts: List global shortcuts
|
||||
version: Print hyprland version
|
||||
CONFIGURATION COMMANDS:
|
||||
keyword <keyword> [args]: Execute a keyword
|
||||
getoption <option>: Get value of <option>
|
||||
reload: Reload configurations
|
||||
PLUGIN:
|
||||
plugin list: List loaded plugins
|
||||
plugin load <path>: Load plugin from <path>
|
||||
plugin unload <path>: Unload plugin at <path>
|
||||
THEMING:
|
||||
hyprpaper <keywords> Issue hyprpaper keywords using IPC
|
||||
splash: Prints the current random splash
|
||||
cursorpos: Get the current cursor position in global layout coordinates
|
||||
setcursor <theme> <size>: Set cursor theme and size, (except for GTK)
|
||||
ADDITIONAL COMMANDS:
|
||||
dispatch <name> [args]: Run a dispatcher
|
||||
kill: Enter kill mode, where you can kill an app by clicking on it,
|
||||
use ESCAPE to quit kill mode
|
||||
switchxkblayout <args>: Sets the xkb layout index for a keyboard, see wiki for details
|
||||
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:
|
||||
const std::string USAGE = R"#(usage: hyprctl [(opt)flags] [command] [(opt)args]
|
||||
|
||||
commands:
|
||||
activewindow
|
||||
activeworkspace
|
||||
binds
|
||||
clients
|
||||
cursorpos
|
||||
decorations
|
||||
devices
|
||||
dispatch
|
||||
getoption
|
||||
globalshortcuts
|
||||
hyprpaper
|
||||
instances
|
||||
keyword
|
||||
kill
|
||||
layers
|
||||
layouts
|
||||
monitors
|
||||
notify
|
||||
plugin
|
||||
reload
|
||||
setcursor
|
||||
seterror
|
||||
setprop
|
||||
splash
|
||||
switchxkblayout
|
||||
systeminfo
|
||||
version
|
||||
workspacerules
|
||||
workspaces
|
||||
|
||||
flags:
|
||||
-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 ';'
|
||||
--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;
|
||||
|
||||
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;
|
||||
|
||||
// read lock
|
||||
|
@ -94,7 +87,9 @@ std::vector<SInstanceData> instances() {
|
|||
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);
|
||||
|
||||
try {
|
||||
data->time = std::stoull(data->id.substr(data->id.find_first_of('_') + 1));
|
||||
} catch (std::exception& e) { continue; }
|
||||
|
||||
// read file
|
||||
std::ifstream ifs(el.path().string());
|
||||
|
@ -102,7 +97,9 @@ std::vector<SInstanceData> instances() {
|
|||
int i = 0;
|
||||
for (std::string line; std::getline(ifs, line); ++i) {
|
||||
if (i == 0) {
|
||||
try {
|
||||
data->pid = std::stoull(line);
|
||||
} catch (std::exception& e) { continue; }
|
||||
} else if (i == 1) {
|
||||
data->wlSocket = line;
|
||||
} else
|
||||
|
@ -309,6 +306,8 @@ int main(int argc, char** argv) {
|
|||
if (ARGS[i] == "-j" && !fullArgs.contains("j")) {
|
||||
fullArgs += "j";
|
||||
json = true;
|
||||
} else if (ARGS[i] == "-r" && !fullArgs.contains("r")) {
|
||||
fullArgs += "r";
|
||||
} else if (ARGS[i] == "--batch") {
|
||||
fullRequest = "--batch ";
|
||||
} 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");
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -379,42 +378,8 @@ int main(int argc, char** argv) {
|
|||
|
||||
if (fullRequest.contains("/--batch"))
|
||||
batchRequest(fullRequest);
|
||||
else if (fullRequest.contains("/monitors"))
|
||||
request(fullRequest);
|
||||
else if (fullRequest.contains("/clients"))
|
||||
request(fullRequest);
|
||||
else if (fullRequest.contains("/workspaces"))
|
||||
request(fullRequest);
|
||||
else if (fullRequest.contains("/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("/hyprpaper"))
|
||||
requestHyprpaper(fullRequest);
|
||||
else if (fullRequest.contains("/switchxkblayout"))
|
||||
request(fullRequest, 2);
|
||||
else if (fullRequest.contains("/seterror"))
|
||||
|
@ -435,15 +400,10 @@ int main(int argc, char** argv) {
|
|||
request(fullRequest, 2);
|
||||
else if (fullRequest.contains("/decorations"))
|
||||
request(fullRequest, 1);
|
||||
else if (fullRequest.contains("/hyprpaper"))
|
||||
requestHyprpaper(fullRequest);
|
||||
else if (fullRequest.contains("/layouts"))
|
||||
request(fullRequest);
|
||||
else if (fullRequest.contains("/--help"))
|
||||
printf("%s", USAGE.c_str());
|
||||
else {
|
||||
printf("%s\n", USAGE.c_str());
|
||||
return 1;
|
||||
request(fullRequest);
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
|
|
|
@ -20,11 +20,18 @@ std::string DataState::getDataStatePath() {
|
|||
return std::string{HOME} + "/.local/share/hyprpm";
|
||||
}
|
||||
|
||||
std::string DataState::getHeadersPath() {
|
||||
return getDataStatePath() + "/headersRoot";
|
||||
}
|
||||
|
||||
void DataState::ensureStateStoreExists() {
|
||||
const auto PATH = getDataStatePath();
|
||||
|
||||
if (!std::filesystem::exists(PATH))
|
||||
std::filesystem::create_directories(PATH);
|
||||
|
||||
if (!std::filesystem::exists(getHeadersPath()))
|
||||
std::filesystem::create_directories(getHeadersPath());
|
||||
}
|
||||
|
||||
void DataState::addNewPluginRepo(const SPluginRepository& repo) {
|
||||
|
@ -47,7 +54,8 @@ void DataState::addNewPluginRepo(const SPluginRepository& repo) {
|
|||
|
||||
DATA.emplace(p.name, toml::table{
|
||||
{"filename", p.name + ".so"},
|
||||
{"enabled", p.enabled}
|
||||
{"enabled", p.enabled},
|
||||
{"failed", p.failed}
|
||||
});
|
||||
}
|
||||
// clang-format on
|
||||
|
@ -63,7 +71,10 @@ bool DataState::pluginRepoExists(const std::string& urlOrName) {
|
|||
const auto PATH = getDataStatePath();
|
||||
|
||||
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;
|
||||
|
||||
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();
|
||||
|
||||
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;
|
||||
|
||||
auto STATE = toml::parse_file(entry.path().string() + "/state.toml");
|
||||
|
@ -153,7 +167,10 @@ std::vector<SPluginRepository> DataState::getAllRepositories() {
|
|||
std::vector<SPluginRepository> repos;
|
||||
|
||||
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;
|
||||
|
||||
auto STATE = toml::parse_file(entry.path().string() + "/state.toml");
|
||||
|
@ -172,9 +189,10 @@ std::vector<SPluginRepository> DataState::getAllRepositories() {
|
|||
continue;
|
||||
|
||||
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("");
|
||||
|
||||
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);
|
||||
|
@ -189,7 +207,10 @@ bool DataState::setPluginEnabled(const std::string& name, bool enabled) {
|
|||
const auto PATH = getDataStatePath();
|
||||
|
||||
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;
|
||||
|
||||
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)
|
||||
continue;
|
||||
|
||||
const auto FAILED = STATE[key]["failed"].value_or(false);
|
||||
|
||||
if (FAILED)
|
||||
return false;
|
||||
|
||||
(*STATE[key].as_table()).insert_or_assign("enabled", enabled);
|
||||
|
||||
std::ofstream state(entry.path().string() + "/state.toml", std::ios::trunc);
|
||||
|
|
|
@ -10,6 +10,7 @@ struct SGlobalState {
|
|||
|
||||
namespace DataState {
|
||||
std::string getDataStatePath();
|
||||
std::string getHeadersPath();
|
||||
void ensureStateStoreExists();
|
||||
void addNewPluginRepo(const SPluginRepository& repo);
|
||||
void removePluginRepo(const std::string& urlOrName);
|
||||
|
|
|
@ -19,6 +19,7 @@ class CManifest {
|
|||
std::vector<std::string> authors;
|
||||
std::vector<std::string> buildSteps;
|
||||
std::string output;
|
||||
bool failed = false;
|
||||
};
|
||||
|
||||
struct {
|
||||
|
|
|
@ -6,7 +6,8 @@
|
|||
struct SPlugin {
|
||||
std::string name;
|
||||
std::string filename;
|
||||
bool enabled;
|
||||
bool enabled = false;
|
||||
bool failed = false;
|
||||
};
|
||||
|
||||
struct SPluginRepository {
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include <thread>
|
||||
#include <fstream>
|
||||
#include <algorithm>
|
||||
#include <format>
|
||||
|
||||
#include <toml++/toml.hpp>
|
||||
|
||||
|
@ -78,6 +79,8 @@ SHyprlandVersion CPluginManager::getHyprlandVersion() {
|
|||
|
||||
bool CPluginManager::addNewPluginRepo(const std::string& url) {
|
||||
|
||||
const auto HLVER = getHyprlandVersion();
|
||||
|
||||
if (DataState::pluginRepoExists(url)) {
|
||||
std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " Could not clone the plugin repository. Repository already installed.\n";
|
||||
return false;
|
||||
|
@ -170,6 +173,22 @@ bool CPluginManager::addNewPluginRepo(const std::string& url) {
|
|||
message += " version " + pl.version;
|
||||
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.print();
|
||||
|
||||
|
@ -191,16 +210,19 @@ bool CPluginManager::addNewPluginRepo(const std::string& url) {
|
|||
progress.printMessageAbove(std::string{Colors::RESET} + " → Building " + p.name);
|
||||
|
||||
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)) {
|
||||
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)
|
||||
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);
|
||||
|
@ -220,7 +242,7 @@ bool CPluginManager::addNewPluginRepo(const std::string& url) {
|
|||
repo.url = url;
|
||||
repo.hash = repohash;
|
||||
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);
|
||||
|
||||
|
@ -263,8 +285,12 @@ bool CPluginManager::removePluginRepo(const std::string& urlOrName) {
|
|||
eHeadersErrors CPluginManager::headersValid() {
|
||||
const auto HLVER = getHyprlandVersion();
|
||||
|
||||
if (!std::filesystem::exists(DataState::getHeadersPath() + "/share/pkgconfig/hyprland.pc"))
|
||||
return HEADERS_MISSING;
|
||||
|
||||
// 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/"))
|
||||
return HEADERS_MISSING;
|
||||
|
@ -296,10 +322,6 @@ eHeadersErrors CPluginManager::headersValid() {
|
|||
if (!ifs.good())
|
||||
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>()));
|
||||
ifs.close();
|
||||
|
||||
|
@ -314,7 +336,9 @@ eHeadersErrors CPluginManager::headersValid() {
|
|||
return HEADERS_OK;
|
||||
}
|
||||
|
||||
bool CPluginManager::updateHeaders() {
|
||||
bool CPluginManager::updateHeaders(bool force) {
|
||||
|
||||
DataState::ensureStateStoreExists();
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
if (headersValid() == HEADERS_OK) {
|
||||
std::cout << "\n" << std::string{Colors::GREEN} + "✔" + Colors::RESET + " Your headers are already up-to-date.\n";
|
||||
auto GLOBALSTATE = DataState::getGlobalState();
|
||||
GLOBALSTATE.headersHashCompiled = HLVER.hash;
|
||||
DataState::updateGlobalState(GLOBALSTATE);
|
||||
if (!force && headersValid() == HEADERS_OK) {
|
||||
std::cout << "\n" << std::string{Colors::GREEN} + "✔" + Colors::RESET + " Headers up to date.\n";
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -342,9 +363,9 @@ bool CPluginManager::updateHeaders() {
|
|||
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")) {
|
||||
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");
|
||||
|
||||
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
|
||||
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.m_iSteps = 4;
|
||||
progress.m_szCurrentMessage = "Installing sources";
|
||||
progress.print();
|
||||
|
||||
progress.printMessageAbove(
|
||||
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.");
|
||||
// progress.printMessageAbove(
|
||||
// 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.");
|
||||
|
||||
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)
|
||||
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
|
||||
std::filesystem::remove_all("/tmp/hyprpm/hyprland");
|
||||
|
@ -397,10 +433,6 @@ bool CPluginManager::updateHeaders() {
|
|||
progress.m_szCurrentMessage = "Done!";
|
||||
progress.print();
|
||||
|
||||
auto GLOBALSTATE = DataState::getGlobalState();
|
||||
GLOBALSTATE.headersHashCompiled = HLVER.hash;
|
||||
DataState::updateGlobalState(GLOBALSTATE);
|
||||
|
||||
std::cout << "\n";
|
||||
} else {
|
||||
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();
|
||||
|
||||
CProgressBar progress;
|
||||
progress.m_iMaxSteps = REPOS.size() * 2 + 1;
|
||||
progress.m_iMaxSteps = REPOS.size() * 2 + 2;
|
||||
progress.m_iSteps = 0;
|
||||
progress.m_szCurrentMessage = "Updating repositories";
|
||||
progress.print();
|
||||
|
@ -528,7 +560,8 @@ bool CPluginManager::updatePlugins(bool forceUpdateAll) {
|
|||
progress.printMessageAbove(std::string{Colors::RESET} + " → Building " + p.name);
|
||||
|
||||
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)) {
|
||||
|
@ -566,6 +599,14 @@ bool CPluginManager::updatePlugins(bool forceUpdateAll) {
|
|||
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_szCurrentMessage = "Done!";
|
||||
progress.print();
|
||||
|
@ -696,8 +737,13 @@ void CPluginManager::listAllPlugins() {
|
|||
std::cout << std::string{Colors::RESET} + " → Repository " + r.name + ":\n";
|
||||
|
||||
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);
|
||||
|
||||
eHeadersErrors headersValid();
|
||||
bool updateHeaders();
|
||||
bool updateHeaders(bool force = false);
|
||||
bool updatePlugins(bool forceUpdateAll);
|
||||
|
||||
void listAllPlugins();
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "progress/CProgressBar.hpp"
|
||||
#include "helpers/Colors.hpp"
|
||||
#include "core/PluginManager.hpp"
|
||||
#include "core/DataState.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
@ -8,21 +9,23 @@
|
|||
#include <chrono>
|
||||
#include <thread>
|
||||
|
||||
const std::string HELP = R"#(usage: hyprpm [flags] [<command> [args]]
|
||||
|
||||
LISTING COMMANDS:
|
||||
add: Install a new plugin repository from git
|
||||
remove: Remove an installed plugin repository
|
||||
enable: Enable a plugin
|
||||
disable: Disable a plugin
|
||||
update: Check and update all plugins if needed
|
||||
reload: Rreload hyprpm state. Ensure all enabled plugins are loaded.
|
||||
list: List all installed plugins
|
||||
FLAGS:
|
||||
--notify -> Send a hyprland notification for important events (e.g. load fail)
|
||||
--help -> display this help
|
||||
--verbose -> Enable too much logging
|
||||
|
||||
const std::string HELP = R"#(┏ hyprpm, a Hyprland Plugin Manager
|
||||
┃
|
||||
┣ add [url] → Install a new plugin repository from git
|
||||
┣ remove [url/name] → Remove an installed plugin repository
|
||||
┣ enable [name] → Enable a plugin
|
||||
┣ disable [name] → Disable a plugin
|
||||
┣ update → Check and update all plugins if needed
|
||||
┣ reload → Reload hyprpm state. Ensure all enabled plugins are loaded.
|
||||
┣ list → List all installed plugins
|
||||
┃
|
||||
┣ Flags:
|
||||
┃
|
||||
┣ --notify | -n → Send a hyprland notification for important events (e.g. load fail)
|
||||
┣ --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) {
|
||||
|
@ -37,7 +40,7 @@ int main(int argc, char** argv, char** envp) {
|
|||
}
|
||||
|
||||
std::vector<std::string> command;
|
||||
bool notify = false, verbose = false;
|
||||
bool notify = false, verbose = false, force = false;
|
||||
|
||||
for (int i = 1; i < argc; ++i) {
|
||||
if (ARGS[i].starts_with("-")) {
|
||||
|
@ -48,6 +51,9 @@ int main(int argc, char** argv, char** envp) {
|
|||
notify = true;
|
||||
} else if (ARGS[i] == "--verbose" || ARGS[i] == "-v") {
|
||||
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 {
|
||||
std::cerr << "Unrecognized option " << ARGS[i];
|
||||
return 1;
|
||||
|
@ -81,9 +87,13 @@ int main(int argc, char** argv, char** envp) {
|
|||
return g_pPluginManager->removePluginRepo(command[1]) ? 0 : 1;
|
||||
} else if (command[0] == "update") {
|
||||
bool headersValid = g_pPluginManager->headersValid() == HEADERS_OK;
|
||||
bool headers = g_pPluginManager->updateHeaders();
|
||||
bool headers = g_pPluginManager->updateHeaders(force);
|
||||
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)
|
||||
return 1;
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
cairo,
|
||||
git,
|
||||
hyprland-protocols,
|
||||
hyprlang,
|
||||
jq,
|
||||
libGL,
|
||||
libdrm,
|
||||
|
@ -75,6 +76,7 @@ assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been remov
|
|||
cairo
|
||||
git
|
||||
hyprland-protocols
|
||||
hyprlang
|
||||
libdrm
|
||||
libGL
|
||||
libinput
|
||||
|
|
|
@ -10,21 +10,19 @@
|
|||
(builtins.substring 4 2 longDate)
|
||||
(builtins.substring 6 2 longDate)
|
||||
]);
|
||||
|
||||
mkJoinedOverlays = overlays: final: prev:
|
||||
lib.foldl' (attrs: overlay: attrs // (overlay final prev)) {} overlays;
|
||||
in {
|
||||
# Contains what a user is most likely to care about:
|
||||
# Hyprland itself, XDPH and the Share Picker.
|
||||
default = mkJoinedOverlays (with self.overlays; [
|
||||
default = lib.composeManyExtensions (with self.overlays; [
|
||||
hyprland-packages
|
||||
hyprland-extras
|
||||
]);
|
||||
|
||||
# Packages for variations of Hyprland, dependencies included.
|
||||
hyprland-packages = mkJoinedOverlays [
|
||||
hyprland-packages = lib.composeManyExtensions [
|
||||
# Dependencies
|
||||
inputs.hyprland-protocols.overlays.default
|
||||
inputs.hyprlang.overlays.default
|
||||
self.overlays.wlroots-hyprland
|
||||
self.overlays.udis86
|
||||
# Hyprland packages themselves
|
||||
|
@ -34,9 +32,9 @@ in {
|
|||
hyprland = final.callPackage ./default.nix {
|
||||
stdenv = final.gcc13Stdenv;
|
||||
version = "${props.version}+date=${date}_${self.shortRev or "dirty"}";
|
||||
wlroots = final.wlroots-hyprland;
|
||||
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;
|
||||
};
|
||||
hyprland-unwrapped = final.hyprland.override {wrapRuntimeDeps = false;};
|
||||
|
@ -59,12 +57,12 @@ in {
|
|||
|
||||
# Packages for extra software recommended for usage with Hyprland,
|
||||
# including forked or patched packages for compatibility.
|
||||
hyprland-extras = mkJoinedOverlays [
|
||||
hyprland-extras = lib.composeManyExtensions [
|
||||
inputs.xdph.overlays.xdg-desktop-portal-hyprland
|
||||
];
|
||||
|
||||
udis86 = final: prev: {
|
||||
udis86 = final.callPackage ./udis86.nix {};
|
||||
udis86-hyprland = final.callPackage ./udis86.nix {};
|
||||
};
|
||||
|
||||
# Patched version of wlroots for Hyprland.
|
||||
|
|
|
@ -34,16 +34,17 @@ index 1d2c7f9f..c5ef4e67 100644
|
|||
headers = globber.stdout().strip().split('\n')
|
||||
foreach file : headers
|
||||
diff --git a/src/meson.build b/src/meson.build
|
||||
index 0af864b9..38723b8c 100644
|
||||
index 45701f5f..3505cefe 100644
|
||||
--- a/src/meson.build
|
||||
+++ b/src/meson.build
|
||||
@@ -9,16 +9,16 @@ executable('Hyprland', src,
|
||||
@@ -9,17 +9,17 @@ executable('Hyprland', src,
|
||||
server_protos,
|
||||
dependency('wayland-server'),
|
||||
dependency('wayland-client'),
|
||||
- wlroots.get_variable('wlroots'),
|
||||
+ dependency('wlroots'),
|
||||
dependency('cairo'),
|
||||
dependency('hyprlang', version: '>= 0.3.2'),
|
||||
dependency('libdrm'),
|
||||
dependency('egl'),
|
||||
dependency('xkbcommon'),
|
||||
|
|
|
@ -8,7 +8,7 @@ CRT_REV=$(rg rev flake.nix | awk '{ print substr($3, 2, 40) }')
|
|||
if [ "$SUB_REV" != "$CRT_REV" ]; then
|
||||
echo "Updating wlroots..."
|
||||
# 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
|
||||
|
||||
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',
|
||||
version: '>=1.25',
|
||||
version: '>=1.32',
|
||||
fallback: 'wayland-protocols',
|
||||
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,
|
|
@ -81,26 +81,6 @@ CCompositor::CCompositor() {
|
|||
|
||||
CCompositor::~CCompositor() {
|
||||
cleanup();
|
||||
g_pDecorationPositioner.reset();
|
||||
g_pPluginSystem.reset();
|
||||
g_pHyprNotificationOverlay.reset();
|
||||
g_pDebugOverlay.reset();
|
||||
g_pEventManager.reset();
|
||||
g_pSessionLockManager.reset();
|
||||
g_pProtocolManager.reset();
|
||||
g_pXWaylandManager.reset();
|
||||
g_pHyprRenderer.reset();
|
||||
g_pHyprOpenGL.reset();
|
||||
g_pInputManager.reset();
|
||||
g_pThreadManager.reset();
|
||||
g_pConfigManager.reset();
|
||||
g_pLayoutManager.reset();
|
||||
g_pHyprError.reset();
|
||||
g_pConfigManager.reset();
|
||||
g_pAnimationManager.reset();
|
||||
g_pKeybindManager.reset();
|
||||
g_pHookSystem.reset();
|
||||
g_pWatchdog.reset();
|
||||
}
|
||||
|
||||
void CCompositor::setRandomSplash() {
|
||||
|
@ -119,8 +99,11 @@ void CCompositor::initServer() {
|
|||
|
||||
// register crit signal handler
|
||||
wl_event_loop_add_signal(m_sWLEventLoop, SIGTERM, handleCritSignal, nullptr);
|
||||
|
||||
if (!envEnabled("HYPRLAND_NO_CRASHREPORTER")) {
|
||||
signal(SIGSEGV, handleUnrecoverableSignal);
|
||||
signal(SIGABRT, handleUnrecoverableSignal);
|
||||
}
|
||||
signal(SIGUSR1, handleUserSignal);
|
||||
|
||||
initManagers(STAGE_PRIORITY);
|
||||
|
@ -135,10 +118,10 @@ void CCompositor::initServer() {
|
|||
else
|
||||
wlr_log_init(WLR_ERROR, Debug::wlrLog);
|
||||
|
||||
m_sWLRBackend = wlr_backend_autocreate(m_sWLDisplay, &m_sWLRSession);
|
||||
m_sWLRBackend = wlr_backend_autocreate(m_sWLEventLoop, &m_sWLRSession);
|
||||
|
||||
if (!m_sWLRBackend) {
|
||||
Debug::log(CRIT, "m_sWLRBackend was NULL!");
|
||||
Debug::log(CRIT, "m_sWLRBackend was NULL! This usually means wlroots could not find a GPU or enountered some issues.");
|
||||
throwError("wlr_backend_autocreate() failed!");
|
||||
}
|
||||
|
||||
|
@ -151,7 +134,7 @@ void CCompositor::initServer() {
|
|||
m_sWLRRenderer = wlr_gles2_renderer_create_with_drm_fd(m_iDRMFD);
|
||||
|
||||
if (!m_sWLRRenderer) {
|
||||
Debug::log(CRIT, "m_sWLRRenderer was NULL!");
|
||||
Debug::log(CRIT, "m_sWLRRenderer was NULL! This usually means wlroots could not find a GPU or enountered some issues.");
|
||||
throwError("wlr_gles2_renderer_create_with_drm_fd() failed!");
|
||||
}
|
||||
|
||||
|
@ -259,7 +242,7 @@ void CCompositor::initServer() {
|
|||
|
||||
m_sWLRActivation = wlr_xdg_activation_v1_create(m_sWLDisplay);
|
||||
|
||||
m_sWLRHeadlessBackend = wlr_headless_backend_create(m_sWLDisplay);
|
||||
m_sWLRHeadlessBackend = wlr_headless_backend_create(m_sWLEventLoop);
|
||||
|
||||
m_sWLRSessionLockMgr = wlr_session_lock_manager_v1_create(m_sWLDisplay);
|
||||
|
||||
|
@ -324,6 +307,7 @@ void CCompositor::initAllSignals() {
|
|||
addWLSignal(&m_sWLRGammaCtrlMgr->events.set_gamma, &Events::listen_setGamma, m_sWLRGammaCtrlMgr, "GammaCtrlMgr");
|
||||
addWLSignal(&m_sWLRCursorShapeMgr->events.request_set_shape, &Events::listen_setCursorShape, m_sWLRCursorShapeMgr, "CursorShapeMgr");
|
||||
addWLSignal(&m_sWLRTearingControlMgr->events.new_object, &Events::listen_newTearingHint, m_sWLRTearingControlMgr, "TearingControlMgr");
|
||||
addWLSignal(&m_sWLRKbShInhibitMgr->events.new_inhibitor, &Events::listen_newShortcutInhibitor, m_sWLRKbShInhibitMgr, "ShortcutInhibitMgr");
|
||||
|
||||
if (m_sWRLDRMLeaseMgr)
|
||||
addWLSignal(&m_sWRLDRMLeaseMgr->events.request, &Events::listen_leaseRequest, &m_sWRLDRMLeaseMgr, "DRM");
|
||||
|
@ -332,10 +316,67 @@ void CCompositor::initAllSignals() {
|
|||
addWLSignal(&m_sWLRSession->events.active, &Events::listen_sessionActive, m_sWLRSession, "Session");
|
||||
}
|
||||
|
||||
void CCompositor::removeAllSignals() {
|
||||
removeWLSignal(&Events::listen_newOutput);
|
||||
removeWLSignal(&Events::listen_newXDGToplevel);
|
||||
removeWLSignal(&Events::listen_mouseMove);
|
||||
removeWLSignal(&Events::listen_mouseMoveAbsolute);
|
||||
removeWLSignal(&Events::listen_mouseButton);
|
||||
removeWLSignal(&Events::listen_mouseAxis);
|
||||
removeWLSignal(&Events::listen_mouseFrame);
|
||||
removeWLSignal(&Events::listen_swipeBegin);
|
||||
removeWLSignal(&Events::listen_swipeUpdate);
|
||||
removeWLSignal(&Events::listen_swipeEnd);
|
||||
removeWLSignal(&Events::listen_pinchBegin);
|
||||
removeWLSignal(&Events::listen_pinchUpdate);
|
||||
removeWLSignal(&Events::listen_pinchEnd);
|
||||
removeWLSignal(&Events::listen_touchBegin);
|
||||
removeWLSignal(&Events::listen_touchEnd);
|
||||
removeWLSignal(&Events::listen_touchUpdate);
|
||||
removeWLSignal(&Events::listen_touchFrame);
|
||||
removeWLSignal(&Events::listen_holdBegin);
|
||||
removeWLSignal(&Events::listen_holdEnd);
|
||||
removeWLSignal(&Events::listen_newInput);
|
||||
removeWLSignal(&Events::listen_requestMouse);
|
||||
removeWLSignal(&Events::listen_requestSetSel);
|
||||
removeWLSignal(&Events::listen_requestDrag);
|
||||
removeWLSignal(&Events::listen_startDrag);
|
||||
removeWLSignal(&Events::listen_requestSetSel);
|
||||
removeWLSignal(&Events::listen_requestSetPrimarySel);
|
||||
removeWLSignal(&Events::listen_newLayerSurface);
|
||||
removeWLSignal(&Events::listen_change);
|
||||
removeWLSignal(&Events::listen_outputMgrApply);
|
||||
removeWLSignal(&Events::listen_outputMgrTest);
|
||||
removeWLSignal(&Events::listen_newConstraint);
|
||||
removeWLSignal(&Events::listen_NewXDGDeco);
|
||||
removeWLSignal(&Events::listen_newVirtPtr);
|
||||
removeWLSignal(&Events::listen_newVirtualKeyboard);
|
||||
removeWLSignal(&Events::listen_RendererDestroy);
|
||||
removeWLSignal(&Events::listen_newIdleInhibitor);
|
||||
removeWLSignal(&Events::listen_powerMgrSetMode);
|
||||
removeWLSignal(&Events::listen_newIME);
|
||||
removeWLSignal(&Events::listen_newTextInput);
|
||||
removeWLSignal(&Events::listen_activateXDG);
|
||||
removeWLSignal(&Events::listen_newSessionLock);
|
||||
removeWLSignal(&Events::listen_setGamma);
|
||||
removeWLSignal(&Events::listen_setCursorShape);
|
||||
removeWLSignal(&Events::listen_newTearingHint);
|
||||
removeWLSignal(&Events::listen_newShortcutInhibitor);
|
||||
|
||||
if (m_sWRLDRMLeaseMgr)
|
||||
removeWLSignal(&Events::listen_leaseRequest);
|
||||
|
||||
if (m_sWLRSession)
|
||||
removeWLSignal(&Events::listen_sessionActive);
|
||||
}
|
||||
|
||||
void CCompositor::cleanup() {
|
||||
if (!m_sWLDisplay || m_bIsShuttingDown)
|
||||
return;
|
||||
|
||||
signal(SIGABRT, SIG_DFL);
|
||||
signal(SIGSEGV, SIG_DFL);
|
||||
|
||||
removeLockFile();
|
||||
|
||||
m_bIsShuttingDown = true;
|
||||
|
@ -362,8 +403,8 @@ void CCompositor::cleanup() {
|
|||
for (auto& m : m_vMonitors) {
|
||||
g_pHyprOpenGL->destroyMonitorResources(m.get());
|
||||
|
||||
wlr_output_enable(m->output, false);
|
||||
wlr_output_commit(m->output);
|
||||
wlr_output_state_set_enabled(m->state.wlr(), false);
|
||||
m->state.commit();
|
||||
}
|
||||
|
||||
m_vMonitors.clear();
|
||||
|
@ -373,8 +414,32 @@ void CCompositor::cleanup() {
|
|||
g_pXWaylandManager->m_sWLRXWayland = nullptr;
|
||||
}
|
||||
|
||||
removeAllSignals();
|
||||
|
||||
g_pInputManager.reset();
|
||||
|
||||
wl_display_destroy_clients(g_pCompositor->m_sWLDisplay);
|
||||
|
||||
g_pDecorationPositioner.reset();
|
||||
g_pPluginSystem.reset();
|
||||
g_pHyprNotificationOverlay.reset();
|
||||
g_pDebugOverlay.reset();
|
||||
g_pEventManager.reset();
|
||||
g_pSessionLockManager.reset();
|
||||
g_pProtocolManager.reset();
|
||||
g_pHyprRenderer.reset();
|
||||
g_pHyprOpenGL.reset();
|
||||
g_pThreadManager.reset();
|
||||
g_pConfigManager.reset();
|
||||
g_pLayoutManager.reset();
|
||||
g_pHyprError.reset();
|
||||
g_pConfigManager.reset();
|
||||
g_pAnimationManager.reset();
|
||||
g_pKeybindManager.reset();
|
||||
g_pHookSystem.reset();
|
||||
g_pWatchdog.reset();
|
||||
g_pXWaylandManager.reset();
|
||||
|
||||
wl_display_terminate(m_sWLDisplay);
|
||||
|
||||
m_sWLDisplay = nullptr;
|
||||
|
@ -408,6 +473,9 @@ void CCompositor::initManagers(eManagersInitStage stage) {
|
|||
Debug::log(LOG, "Creating the ThreadManager!");
|
||||
g_pThreadManager = std::make_unique<CThreadManager>();
|
||||
|
||||
Debug::log(LOG, "Creating CHyprCtl");
|
||||
g_pHyprCtl = std::make_unique<CHyprCtl>();
|
||||
|
||||
Debug::log(LOG, "Creating the InputManager!");
|
||||
g_pInputManager = std::make_unique<CInputManager>();
|
||||
|
||||
|
@ -629,38 +697,30 @@ bool CCompositor::windowExists(CWindow* pWindow) {
|
|||
return false;
|
||||
}
|
||||
|
||||
CWindow* CCompositor::vectorToWindowTiled(const Vector2D& pos) {
|
||||
bool CCompositor::monitorExists(CMonitor* pMonitor) {
|
||||
for (auto& m : m_vRealMonitors) {
|
||||
if (m.get() == pMonitor)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
CWindow* CCompositor::vectorToWindowUnified(const Vector2D& pos, uint8_t properties, CWindow* pIgnoreWindow) {
|
||||
const auto PMONITOR = getMonitorFromVector(pos);
|
||||
|
||||
if (PMONITOR->specialWorkspaceID) {
|
||||
for (auto& w : m_vWindows) {
|
||||
CBox box = {w->m_vPosition.x, w->m_vPosition.y, w->m_vSize.x, w->m_vSize.y};
|
||||
if (w->m_iWorkspaceID == PMONITOR->specialWorkspaceID && box.containsPoint(pos) && !w->m_bIsFloating && !w->isHidden() && !w->m_bNoFocus)
|
||||
return w.get();
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& w : m_vWindows) {
|
||||
CBox box = {w->m_vPosition.x, w->m_vPosition.y, w->m_vSize.x, w->m_vSize.y};
|
||||
if (w->m_bIsMapped && box.containsPoint(pos) && w->m_iWorkspaceID == PMONITOR->activeWorkspace && !w->m_bIsFloating && !w->isHidden() && !w->m_bNoFocus)
|
||||
return w.get();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
CWindow* CCompositor::vectorToWindowIdeal(const Vector2D& pos, CWindow* pIgnoreWindow) {
|
||||
const auto PMONITOR = getMonitorFromVector(pos);
|
||||
static auto* const PRESIZEONBORDER = &g_pConfigManager->getConfigValuePtr("general:resize_on_border")->intValue;
|
||||
static auto* const PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue;
|
||||
static auto* const PBORDERGRABEXTEND = &g_pConfigManager->getConfigValuePtr("general:extend_border_grab_area")->intValue;
|
||||
const auto BORDER_GRAB_AREA = *PRESIZEONBORDER ? *PBORDERSIZE + *PBORDERGRABEXTEND : 0;
|
||||
static auto* const PRESIZEONBORDER = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("general:resize_on_border");
|
||||
static auto* const PBORDERSIZE = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("general:border_size");
|
||||
static auto* const PBORDERGRABEXTEND = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("general:extend_border_grab_area");
|
||||
static auto* const PSPECIALFALLTHRU = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("input:special_fallthrough");
|
||||
const auto BORDER_GRAB_AREA = **PRESIZEONBORDER ? **PBORDERSIZE + **PBORDERGRABEXTEND : 0;
|
||||
|
||||
// pinned windows on top of floating regardless
|
||||
if (properties & ALLOW_FLOATING) {
|
||||
for (auto& w : m_vWindows | std::views::reverse) {
|
||||
const auto BB = w->getWindowInputBox();
|
||||
const auto BB = w->getWindowBoxUnified(properties);
|
||||
CBox box = {BB.x - BORDER_GRAB_AREA, BB.y - BORDER_GRAB_AREA, BB.width + 2 * BORDER_GRAB_AREA, BB.height + 2 * BORDER_GRAB_AREA};
|
||||
if (w->m_bIsFloating && w->m_bIsMapped && !w->isHidden() && !w->m_bX11ShouldntFocus && w->m_bPinned && !w->m_bNoFocus && w.get() != pIgnoreWindow) {
|
||||
if (w->m_bIsFloating && w->m_bIsMapped && !w->isHidden() && !w->m_bX11ShouldntFocus && w->m_bPinned && !w->m_sAdditionalConfigData.noFocus &&
|
||||
w.get() != pIgnoreWindow) {
|
||||
if (box.containsPoint({m_sWLRCursor->x, m_sWLRCursor->y}))
|
||||
return w.get();
|
||||
|
||||
|
@ -670,17 +730,19 @@ CWindow* CCompositor::vectorToWindowIdeal(const Vector2D& pos, CWindow* pIgnoreW
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto windowForWorkspace = [&](bool special) -> CWindow* {
|
||||
// first loop over floating cuz they're above, m_lWindows should be sorted bottom->top, for tiled it doesn't matter.
|
||||
auto floating = [&](bool aboveFullscreen) -> CWindow* {
|
||||
for (auto& w : m_vWindows | std::views::reverse) {
|
||||
|
||||
if (special && !isWorkspaceSpecial(w->m_iWorkspaceID)) // because special floating may creep up into regular
|
||||
continue;
|
||||
|
||||
const auto BB = w->getWindowInputBox();
|
||||
const auto BB = w->getWindowBoxUnified(properties);
|
||||
CBox box = {BB.x - BORDER_GRAB_AREA, BB.y - BORDER_GRAB_AREA, BB.width + 2 * BORDER_GRAB_AREA, BB.height + 2 * BORDER_GRAB_AREA};
|
||||
if (w->m_bIsFloating && w->m_bIsMapped && isWorkspaceVisible(w->m_iWorkspaceID) && !w->isHidden() && !w->m_bPinned && !w->m_bNoFocus && w.get() != pIgnoreWindow) {
|
||||
if (w->m_bIsFloating && w->m_bIsMapped && isWorkspaceVisible(w->m_iWorkspaceID) && !w->isHidden() && !w->m_bPinned && !w->m_sAdditionalConfigData.noFocus &&
|
||||
w.get() != pIgnoreWindow && (!aboveFullscreen || w->m_bCreatedOverFullscreen)) {
|
||||
// OR windows should add focus to parent
|
||||
if (w->m_bX11ShouldntFocus && w->m_iX11Type != 2)
|
||||
continue;
|
||||
|
@ -703,19 +765,36 @@ CWindow* CCompositor::vectorToWindowIdeal(const Vector2D& pos, CWindow* pIgnoreW
|
|||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
};
|
||||
|
||||
if (properties & ALLOW_FLOATING) {
|
||||
// first loop over floating cuz they're above, m_lWindows should be sorted bottom->top, for tiled it doesn't matter.
|
||||
auto found = floating(true);
|
||||
if (found)
|
||||
return found;
|
||||
}
|
||||
|
||||
if (properties & FLOATING_ONLY)
|
||||
return floating(false);
|
||||
|
||||
const int64_t WORKSPACEID = special ? PMONITOR->specialWorkspaceID : PMONITOR->activeWorkspace;
|
||||
const auto PWORKSPACE = getWorkspaceByID(WORKSPACEID);
|
||||
|
||||
if (PWORKSPACE->m_bHasFullscreenWindow)
|
||||
return getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID);
|
||||
|
||||
auto found = floating(false);
|
||||
if (found)
|
||||
return found;
|
||||
|
||||
// for windows, we need to check their extensions too, first.
|
||||
for (auto& w : m_vWindows) {
|
||||
if (special != isWorkspaceSpecial(w->m_iWorkspaceID))
|
||||
continue;
|
||||
|
||||
if (!w->m_bIsX11 && !w->m_bIsFloating && w->m_bIsMapped && w->m_iWorkspaceID == WORKSPACEID && !w->isHidden() && !w->m_bX11ShouldntFocus && !w->m_bNoFocus &&
|
||||
w.get() != pIgnoreWindow) {
|
||||
if (!w->m_bIsX11 && !w->m_bIsFloating && w->m_bIsMapped && w->m_iWorkspaceID == WORKSPACEID && !w->isHidden() && !w->m_bX11ShouldntFocus &&
|
||||
!w->m_sAdditionalConfigData.noFocus && w.get() != pIgnoreWindow) {
|
||||
if (w->hasPopupAt(pos))
|
||||
return w.get();
|
||||
}
|
||||
|
@ -725,9 +804,9 @@ CWindow* CCompositor::vectorToWindowIdeal(const Vector2D& pos, CWindow* pIgnoreW
|
|||
if (special != isWorkspaceSpecial(w->m_iWorkspaceID))
|
||||
continue;
|
||||
|
||||
CBox box = {w->m_vPosition, w->m_vSize};
|
||||
if (!w->m_bIsFloating && w->m_bIsMapped && box.containsPoint(pos) && w->m_iWorkspaceID == WORKSPACEID && !w->isHidden() && !w->m_bX11ShouldntFocus && !w->m_bNoFocus &&
|
||||
w.get() != pIgnoreWindow)
|
||||
CBox box = (properties & USE_PROP_TILED) ? w->getWindowBoxUnified(properties) : CBox{w->m_vPosition, w->m_vSize};
|
||||
if (!w->m_bIsFloating && w->m_bIsMapped && box.containsPoint(pos) && w->m_iWorkspaceID == WORKSPACEID && !w->isHidden() && !w->m_bX11ShouldntFocus &&
|
||||
!w->m_sAdditionalConfigData.noFocus && w.get() != pIgnoreWindow)
|
||||
return w.get();
|
||||
}
|
||||
|
||||
|
@ -735,68 +814,17 @@ CWindow* CCompositor::vectorToWindowIdeal(const Vector2D& pos, CWindow* pIgnoreW
|
|||
};
|
||||
|
||||
// special workspace
|
||||
if (PMONITOR->specialWorkspaceID)
|
||||
if (PMONITOR->specialWorkspaceID && !**PSPECIALFALLTHRU)
|
||||
return windowForWorkspace(true);
|
||||
|
||||
return windowForWorkspace(false);
|
||||
}
|
||||
|
||||
CWindow* CCompositor::windowFromCursor() {
|
||||
const auto PMONITOR = getMonitorFromCursor();
|
||||
|
||||
if (PMONITOR->specialWorkspaceID) {
|
||||
for (auto& w : m_vWindows | std::views::reverse) {
|
||||
CBox box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y};
|
||||
if (w->m_bIsFloating && w->m_iWorkspaceID == PMONITOR->specialWorkspaceID && w->m_bIsMapped && box.containsPoint({m_sWLRCursor->x, m_sWLRCursor->y}) &&
|
||||
!w->isHidden() && !w->m_bNoFocus)
|
||||
return w.get();
|
||||
const auto PWINDOW = windowForWorkspace(true);
|
||||
|
||||
if (PWINDOW)
|
||||
return PWINDOW;
|
||||
}
|
||||
|
||||
for (auto& w : m_vWindows) {
|
||||
CBox box = {w->m_vPosition.x, w->m_vPosition.y, w->m_vSize.x, w->m_vSize.y};
|
||||
if (w->m_iWorkspaceID == PMONITOR->specialWorkspaceID && box.containsPoint({m_sWLRCursor->x, m_sWLRCursor->y}) && w->m_bIsMapped && !w->m_bNoFocus)
|
||||
return w.get();
|
||||
}
|
||||
}
|
||||
|
||||
// pinned
|
||||
for (auto& w : m_vWindows | std::views::reverse) {
|
||||
CBox box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y};
|
||||
if (box.containsPoint({m_sWLRCursor->x, m_sWLRCursor->y}) && w->m_bIsMapped && w->m_bIsFloating && w->m_bPinned && !w->m_bNoFocus)
|
||||
return w.get();
|
||||
}
|
||||
|
||||
// first loop over floating cuz they're above, m_lWindows should be sorted bottom->top, for tiled it doesn't matter.
|
||||
for (auto& w : m_vWindows | std::views::reverse) {
|
||||
CBox box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y};
|
||||
if (box.containsPoint({m_sWLRCursor->x, m_sWLRCursor->y}) && w->m_bIsMapped && w->m_bIsFloating && isWorkspaceVisible(w->m_iWorkspaceID) && !w->m_bPinned && !w->m_bNoFocus)
|
||||
return w.get();
|
||||
}
|
||||
|
||||
for (auto& w : m_vWindows) {
|
||||
CBox box = {w->m_vPosition.x, w->m_vPosition.y, w->m_vSize.x, w->m_vSize.y};
|
||||
if (box.containsPoint({m_sWLRCursor->x, m_sWLRCursor->y}) && w->m_bIsMapped && w->m_iWorkspaceID == PMONITOR->activeWorkspace && !w->m_bNoFocus)
|
||||
return w.get();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
CWindow* CCompositor::windowFloatingFromCursor() {
|
||||
for (auto& w : m_vWindows | std::views::reverse) {
|
||||
CBox box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y};
|
||||
if (box.containsPoint({m_sWLRCursor->x, m_sWLRCursor->y}) && w->m_bIsMapped && w->m_bIsFloating && !w->isHidden() && w->m_bPinned && !w->m_bNoFocus)
|
||||
return w.get();
|
||||
}
|
||||
|
||||
for (auto& w : m_vWindows | std::views::reverse) {
|
||||
CBox box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y};
|
||||
if (box.containsPoint({m_sWLRCursor->x, m_sWLRCursor->y}) && w->m_bIsMapped && w->m_bIsFloating && isWorkspaceVisible(w->m_iWorkspaceID) && !w->isHidden() &&
|
||||
!w->m_bPinned && !w->m_bNoFocus)
|
||||
return w.get();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
return windowForWorkspace(false);
|
||||
}
|
||||
|
||||
wlr_surface* CCompositor::vectorWindowToSurface(const Vector2D& pos, CWindow* pWindow, Vector2D& sl) {
|
||||
|
@ -815,7 +843,8 @@ wlr_surface* CCompositor::vectorWindowToSurface(const Vector2D& pos, CWindow* pW
|
|||
wlr_xdg_surface_get_geometry(pWindow->m_uSurface.xdg, geom.pWlr());
|
||||
geom.applyFromWlr();
|
||||
|
||||
const auto PFOUND = wlr_xdg_surface_surface_at(PSURFACE, pos.x - pWindow->m_vRealPosition.vec().x + geom.x, pos.y - pWindow->m_vRealPosition.vec().y + geom.y, &subx, &suby);
|
||||
const auto PFOUND =
|
||||
wlr_xdg_surface_surface_at(PSURFACE, pos.x - pWindow->m_vRealPosition.value().x + geom.x, pos.y - pWindow->m_vRealPosition.value().y + geom.y, &subx, &suby);
|
||||
|
||||
if (PFOUND) {
|
||||
sl.x = subx;
|
||||
|
@ -823,8 +852,8 @@ wlr_surface* CCompositor::vectorWindowToSurface(const Vector2D& pos, CWindow* pW
|
|||
return PFOUND;
|
||||
}
|
||||
|
||||
sl.x = pos.x - pWindow->m_vRealPosition.vec().x;
|
||||
sl.y = pos.y - pWindow->m_vRealPosition.vec().y;
|
||||
sl.x = pos.x - pWindow->m_vRealPosition.value().x;
|
||||
sl.y = pos.y - pWindow->m_vRealPosition.value().y;
|
||||
|
||||
sl.x += geom.x;
|
||||
sl.y += geom.y;
|
||||
|
@ -837,7 +866,7 @@ Vector2D CCompositor::vectorToSurfaceLocal(const Vector2D& vec, CWindow* pWindow
|
|||
return {};
|
||||
|
||||
if (pWindow->m_bIsX11)
|
||||
return vec - pWindow->m_vRealPosition.goalv();
|
||||
return vec - pWindow->m_vRealPosition.goal();
|
||||
|
||||
const auto PSURFACE = pWindow->m_uSurface.xdg;
|
||||
|
||||
|
@ -859,9 +888,9 @@ Vector2D CCompositor::vectorToSurfaceLocal(const Vector2D& vec, CWindow* pWindow
|
|||
geom.applyFromWlr();
|
||||
|
||||
if (std::get<1>(iterData) == -1337 && std::get<2>(iterData) == -1337)
|
||||
return vec - pWindow->m_vRealPosition.goalv();
|
||||
return vec - pWindow->m_vRealPosition.goal();
|
||||
|
||||
return vec - pWindow->m_vRealPosition.goalv() - Vector2D{std::get<1>(iterData), std::get<2>(iterData)} + Vector2D{geom.x, geom.y};
|
||||
return vec - pWindow->m_vRealPosition.goal() - Vector2D{std::get<1>(iterData), std::get<2>(iterData)} + Vector2D{geom.x, geom.y};
|
||||
}
|
||||
|
||||
CMonitor* CCompositor::getMonitorFromOutput(wlr_output* out) {
|
||||
|
@ -874,15 +903,31 @@ CMonitor* CCompositor::getMonitorFromOutput(wlr_output* out) {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
CMonitor* CCompositor::getRealMonitorFromOutput(wlr_output* out) {
|
||||
for (auto& m : m_vRealMonitors) {
|
||||
if (m->output == out) {
|
||||
return m.get();
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void CCompositor::focusWindow(CWindow* pWindow, wlr_surface* pSurface) {
|
||||
|
||||
static auto* const PFOLLOWMOUSE = &g_pConfigManager->getConfigValuePtr("input:follow_mouse")->intValue;
|
||||
static auto* const PFOLLOWMOUSE = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("input:follow_mouse");
|
||||
static auto* const PSPECIALFALLTHROUGH = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("input:special_fallthrough");
|
||||
|
||||
if (g_pCompositor->m_sSeat.exclusiveClient) {
|
||||
Debug::log(LOG, "Disallowing setting focus to a window due to there being an active input inhibitor layer.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!g_pInputManager->m_dExclusiveLSes.empty()) {
|
||||
Debug::log(LOG, "Refusing a keyboard focus to a window because of an exclusive ls");
|
||||
return;
|
||||
}
|
||||
|
||||
g_pLayoutManager->getCurrentLayout()->bringWindowToTop(pWindow);
|
||||
|
||||
if (!pWindow || !windowValidMapped(pWindow)) {
|
||||
|
@ -917,7 +962,7 @@ void CCompositor::focusWindow(CWindow* pWindow, wlr_surface* pSurface) {
|
|||
return;
|
||||
}
|
||||
|
||||
if (pWindow->m_bNoFocus) {
|
||||
if (pWindow->m_sAdditionalConfigData.noFocus) {
|
||||
Debug::log(LOG, "Ignoring focus to nofocus window!");
|
||||
return;
|
||||
}
|
||||
|
@ -928,12 +973,13 @@ void CCompositor::focusWindow(CWindow* pWindow, wlr_surface* pSurface) {
|
|||
if (pWindow->m_bPinned)
|
||||
pWindow->m_iWorkspaceID = m_pLastMonitor->activeWorkspace;
|
||||
|
||||
const auto PMONITOR = getMonitorFromID(pWindow->m_iMonitorID);
|
||||
|
||||
if (!isWorkspaceVisible(pWindow->m_iWorkspaceID)) {
|
||||
// This is to fix incorrect feedback on the focus history.
|
||||
const auto PWORKSPACE = getWorkspaceByID(pWindow->m_iWorkspaceID);
|
||||
// This is to fix incorrect feedback on the focus history.
|
||||
PWORKSPACE->m_pLastFocusedWindow = pWindow;
|
||||
PWORKSPACE->rememberPrevWorkspace(getWorkspaceByID(m_pLastMonitor->activeWorkspace));
|
||||
const auto PMONITOR = getMonitorFromID(PWORKSPACE->m_iMonitorID);
|
||||
PMONITOR->changeWorkspace(PWORKSPACE, false, true);
|
||||
// changeworkspace already calls focusWindow
|
||||
return;
|
||||
|
@ -942,6 +988,11 @@ void CCompositor::focusWindow(CWindow* pWindow, wlr_surface* pSurface) {
|
|||
const auto PLASTWINDOW = m_pLastWindow;
|
||||
m_pLastWindow = pWindow;
|
||||
|
||||
/* If special fallthrough is enabled, this behavior will be disabled, as I have no better idea of nicely tracking which
|
||||
window focuses are "via keybinds" and which ones aren't. */
|
||||
if (PMONITOR->specialWorkspaceID && PMONITOR->specialWorkspaceID != pWindow->m_iWorkspaceID && !pWindow->m_bPinned && !**PSPECIALFALLTHROUGH)
|
||||
PMONITOR->setSpecialWorkspace(nullptr);
|
||||
|
||||
// we need to make the PLASTWINDOW not equal to m_pLastWindow so that RENDERDATA is correct for an unfocused window
|
||||
if (windowValidMapped(PLASTWINDOW)) {
|
||||
PLASTWINDOW->updateDynamicRules();
|
||||
|
@ -1006,7 +1057,7 @@ void CCompositor::focusWindow(CWindow* pWindow, wlr_surface* pSurface) {
|
|||
std::rotate(m_vWindowFocusHistory.begin(), HISTORYPIVOT, HISTORYPIVOT + 1);
|
||||
}
|
||||
|
||||
if (*PFOLLOWMOUSE == 0)
|
||||
if (**PFOLLOWMOUSE == 0)
|
||||
g_pInputManager->sendMotionEventsToFocused();
|
||||
}
|
||||
|
||||
|
@ -1015,10 +1066,8 @@ void CCompositor::focusSurface(wlr_surface* pSurface, CWindow* pWindowOwner) {
|
|||
if (m_sSeat.seat->keyboard_state.focused_surface == pSurface || (pWindowOwner && m_sSeat.seat->keyboard_state.focused_surface == pWindowOwner->m_pWLSurface.wlr()))
|
||||
return; // Don't focus when already focused on this.
|
||||
|
||||
if (g_pSessionLockManager->isSessionLocked()) {
|
||||
wlr_seat_keyboard_clear_focus(m_sSeat.seat);
|
||||
m_pLastFocus = nullptr;
|
||||
}
|
||||
if (g_pSessionLockManager->isSessionLocked() && !g_pSessionLockManager->isSurfaceSessionLock(pSurface))
|
||||
return;
|
||||
|
||||
// Unfocus last surface if should
|
||||
if (m_pLastFocus && !pWindowOwner)
|
||||
|
@ -1072,31 +1121,14 @@ bool CCompositor::windowValidMapped(CWindow* pWindow) {
|
|||
return true;
|
||||
}
|
||||
|
||||
CWindow* CCompositor::getWindowForPopup(wlr_xdg_popup* popup) {
|
||||
for (auto& p : m_vXDGPopups) {
|
||||
if (p->popup == popup)
|
||||
return p->parentWindow;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
wlr_surface* CCompositor::vectorToLayerSurface(const Vector2D& pos, std::vector<std::unique_ptr<SLayerSurface>>* layerSurfaces, Vector2D* sCoords,
|
||||
SLayerSurface** ppLayerSurfaceFound) {
|
||||
for (auto& ls : *layerSurfaces | std::views::reverse) {
|
||||
if (ls->fadingOut || !ls->layerSurface || (ls->layerSurface && !ls->layerSurface->surface->mapped) || ls->alpha.fl() == 0.f)
|
||||
if (ls->fadingOut || !ls->layerSurface || (ls->layerSurface && !ls->layerSurface->surface->mapped) || ls->alpha.value() == 0.f)
|
||||
continue;
|
||||
|
||||
auto SURFACEAT = wlr_layer_surface_v1_surface_at(ls->layerSurface, pos.x - ls->geometry.x, pos.y - ls->geometry.y, &sCoords->x, &sCoords->y);
|
||||
|
||||
if (ls->layerSurface->current.keyboard_interactive && ls->layer >= ZWLR_LAYER_SHELL_V1_LAYER_TOP) {
|
||||
if (!SURFACEAT)
|
||||
SURFACEAT = ls->layerSurface->surface;
|
||||
|
||||
*ppLayerSurfaceFound = ls.get();
|
||||
return SURFACEAT;
|
||||
}
|
||||
|
||||
if (SURFACEAT) {
|
||||
if (!pixman_region32_not_empty(&SURFACEAT->input_region))
|
||||
continue;
|
||||
|
@ -1210,7 +1242,7 @@ void CCompositor::sanityCheckWorkspaces() {
|
|||
if (!isWorkspaceVisible(WORKSPACE->m_iID)) {
|
||||
|
||||
if (WORKSPACE->m_bIsSpecialWorkspace) {
|
||||
if (WORKSPACE->m_fAlpha.fl() > 0.f /* don't abruptly end the fadeout */) {
|
||||
if (WORKSPACE->m_fAlpha.value() > 0.f /* don't abruptly end the fadeout */) {
|
||||
++it;
|
||||
continue;
|
||||
}
|
||||
|
@ -1391,7 +1423,7 @@ void CCompositor::cleanupFadingOut(const int& monid) {
|
|||
|
||||
bool valid = windowExists(w);
|
||||
|
||||
if (!valid || !w->m_bFadingOut || w->m_fAlpha.fl() == 0.f) {
|
||||
if (!valid || !w->m_bFadingOut || w->m_fAlpha.value() == 0.f) {
|
||||
if (valid && !w->m_bReadyToDelete)
|
||||
continue;
|
||||
|
||||
|
@ -1440,7 +1472,7 @@ void CCompositor::cleanupFadingOut(const int& monid) {
|
|||
if (ls->layer == ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND || ls->layer == ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM)
|
||||
g_pHyprOpenGL->markBlurDirtyForMonitor(getMonitorFromID(monid));
|
||||
|
||||
if (ls->fadingOut && ls->readyToDelete && !ls->alpha.isBeingAnimated()) {
|
||||
if (ls->fadingOut && ls->readyToDelete && ls->isFadedOut()) {
|
||||
for (auto& m : m_vMonitors) {
|
||||
for (auto& lsl : m->m_aLayerSurfaceLayers) {
|
||||
if (!lsl.empty() && std::find_if(lsl.begin(), lsl.end(), [&](std::unique_ptr<SLayerSurface>& other) { return other.get() == ls; }) != lsl.end()) {
|
||||
|
@ -1483,7 +1515,7 @@ CWindow* CCompositor::getWindowInDirection(CWindow* pWindow, char dir) {
|
|||
return nullptr;
|
||||
|
||||
// 0 -> history, 1 -> shared length
|
||||
static auto* const PMETHOD = &g_pConfigManager->getConfigValuePtr("binds:focus_preferred_method")->intValue;
|
||||
static auto* const PMETHOD = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("binds:focus_preferred_method");
|
||||
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID);
|
||||
|
||||
|
@ -1545,7 +1577,7 @@ CWindow* CCompositor::getWindowInDirection(CWindow* pWindow, char dir) {
|
|||
break;
|
||||
}
|
||||
|
||||
if (*PMETHOD == 0 /* history */) {
|
||||
if (**PMETHOD == 0 /* history */) {
|
||||
if (intersectLength > 0) {
|
||||
|
||||
// get idx
|
||||
|
@ -1639,7 +1671,7 @@ CWindow* CCompositor::getNextWindowOnWorkspace(CWindow* pWindow, bool focusableO
|
|||
if (floating.has_value() && w->m_bIsFloating != floating.value())
|
||||
continue;
|
||||
|
||||
if (w->m_iWorkspaceID == pWindow->m_iWorkspaceID && w->m_bIsMapped && !w->isHidden() && (!focusableOnly || !w->m_bNoFocus))
|
||||
if (w->m_iWorkspaceID == pWindow->m_iWorkspaceID && w->m_bIsMapped && !w->isHidden() && (!focusableOnly || !w->m_sAdditionalConfigData.noFocus))
|
||||
return w.get();
|
||||
}
|
||||
|
||||
|
@ -1647,7 +1679,7 @@ CWindow* CCompositor::getNextWindowOnWorkspace(CWindow* pWindow, bool focusableO
|
|||
if (floating.has_value() && w->m_bIsFloating != floating.value())
|
||||
continue;
|
||||
|
||||
if (w.get() != pWindow && w->m_iWorkspaceID == pWindow->m_iWorkspaceID && w->m_bIsMapped && !w->isHidden() && (!focusableOnly || !w->m_bNoFocus))
|
||||
if (w.get() != pWindow && w->m_iWorkspaceID == pWindow->m_iWorkspaceID && w->m_bIsMapped && !w->isHidden() && (!focusableOnly || !w->m_sAdditionalConfigData.noFocus))
|
||||
return w.get();
|
||||
}
|
||||
|
||||
|
@ -1668,7 +1700,7 @@ CWindow* CCompositor::getPrevWindowOnWorkspace(CWindow* pWindow, bool focusableO
|
|||
if (floating.has_value() && w->m_bIsFloating != floating.value())
|
||||
continue;
|
||||
|
||||
if (w->m_iWorkspaceID == pWindow->m_iWorkspaceID && w->m_bIsMapped && !w->isHidden() && (!focusableOnly || !w->m_bNoFocus))
|
||||
if (w->m_iWorkspaceID == pWindow->m_iWorkspaceID && w->m_bIsMapped && !w->isHidden() && (!focusableOnly || !w->m_sAdditionalConfigData.noFocus))
|
||||
return w.get();
|
||||
}
|
||||
|
||||
|
@ -1676,7 +1708,7 @@ CWindow* CCompositor::getPrevWindowOnWorkspace(CWindow* pWindow, bool focusableO
|
|||
if (floating.has_value() && w->m_bIsFloating != floating.value())
|
||||
continue;
|
||||
|
||||
if (w.get() != pWindow && w->m_iWorkspaceID == pWindow->m_iWorkspaceID && w->m_bIsMapped && !w->isHidden() && (!focusableOnly || !w->m_bNoFocus))
|
||||
if (w.get() != pWindow && w->m_iWorkspaceID == pWindow->m_iWorkspaceID && w->m_bIsMapped && !w->isHidden() && (!focusableOnly || !w->m_sAdditionalConfigData.noFocus))
|
||||
return w.get();
|
||||
}
|
||||
|
||||
|
@ -1764,8 +1796,15 @@ CWindow* CCompositor::getConstraintWindow(SMouse* pMouse) {
|
|||
}
|
||||
|
||||
CMonitor* CCompositor::getMonitorInDirection(const char& dir) {
|
||||
const auto POSA = m_pLastMonitor->vecPosition;
|
||||
const auto SIZEA = m_pLastMonitor->vecSize;
|
||||
return this->getMonitorInDirection(m_pLastMonitor, dir);
|
||||
}
|
||||
|
||||
CMonitor* CCompositor::getMonitorInDirection(CMonitor* pSourceMonitor, const char& dir) {
|
||||
if (!pSourceMonitor)
|
||||
return nullptr;
|
||||
|
||||
const auto POSA = pSourceMonitor->vecPosition;
|
||||
const auto SIZEA = pSourceMonitor->vecSize;
|
||||
|
||||
auto longestIntersect = -1;
|
||||
CMonitor* longestIntersectMonitor = nullptr;
|
||||
|
@ -1844,21 +1883,30 @@ void CCompositor::updateWorkspaceWindows(const int64_t& id) {
|
|||
|
||||
void CCompositor::updateWindowAnimatedDecorationValues(CWindow* pWindow) {
|
||||
// optimization
|
||||
static auto* const ACTIVECOL = (CGradientValueData*)g_pConfigManager->getConfigValuePtr("general:col.active_border")->data.get();
|
||||
static auto* const INACTIVECOL = (CGradientValueData*)g_pConfigManager->getConfigValuePtr("general:col.inactive_border")->data.get();
|
||||
static auto* const NOGROUPACTIVECOL = (CGradientValueData*)g_pConfigManager->getConfigValuePtr("general:col.nogroup_border_active")->data.get();
|
||||
static auto* const NOGROUPINACTIVECOL = (CGradientValueData*)g_pConfigManager->getConfigValuePtr("general:col.nogroup_border")->data.get();
|
||||
static auto* const GROUPACTIVECOL = (CGradientValueData*)g_pConfigManager->getConfigValuePtr("group:col.border_active")->data.get();
|
||||
static auto* const GROUPINACTIVECOL = (CGradientValueData*)g_pConfigManager->getConfigValuePtr("group:col.border_inactive")->data.get();
|
||||
static auto* const GROUPACTIVELOCKEDCOL = (CGradientValueData*)g_pConfigManager->getConfigValuePtr("group:col.border_locked_active")->data.get();
|
||||
static auto* const GROUPINACTIVELOCKEDCOL = (CGradientValueData*)g_pConfigManager->getConfigValuePtr("group:col.border_locked_inactive")->data.get();
|
||||
static auto* const PINACTIVEALPHA = &g_pConfigManager->getConfigValuePtr("decoration:inactive_opacity")->floatValue;
|
||||
static auto* const PACTIVEALPHA = &g_pConfigManager->getConfigValuePtr("decoration:active_opacity")->floatValue;
|
||||
static auto* const PFULLSCREENALPHA = &g_pConfigManager->getConfigValuePtr("decoration:fullscreen_opacity")->floatValue;
|
||||
static auto* const PSHADOWCOL = &g_pConfigManager->getConfigValuePtr("decoration:col.shadow")->intValue;
|
||||
static auto* const PSHADOWCOLINACTIVE = &g_pConfigManager->getConfigValuePtr("decoration:col.shadow_inactive")->intValue;
|
||||
static auto* const PDIMSTRENGTH = &g_pConfigManager->getConfigValuePtr("decoration:dim_strength")->floatValue;
|
||||
static auto* const PDIMENABLED = &g_pConfigManager->getConfigValuePtr("decoration:dim_inactive")->intValue;
|
||||
static auto* const PACTIVECOL = (Hyprlang::CUSTOMTYPE* const*)g_pConfigManager->getConfigValuePtr("general:col.active_border");
|
||||
static auto* const PINACTIVECOL = (Hyprlang::CUSTOMTYPE* const*)g_pConfigManager->getConfigValuePtr("general:col.inactive_border");
|
||||
static auto* const PNOGROUPACTIVECOL = (Hyprlang::CUSTOMTYPE* const*)g_pConfigManager->getConfigValuePtr("general:col.nogroup_border_active");
|
||||
static auto* const PNOGROUPINACTIVECOL = (Hyprlang::CUSTOMTYPE* const*)g_pConfigManager->getConfigValuePtr("general:col.nogroup_border");
|
||||
static auto* const PGROUPACTIVECOL = (Hyprlang::CUSTOMTYPE* const*)g_pConfigManager->getConfigValuePtr("group:col.border_active");
|
||||
static auto* const PGROUPINACTIVECOL = (Hyprlang::CUSTOMTYPE* const*)g_pConfigManager->getConfigValuePtr("group:col.border_inactive");
|
||||
static auto* const PGROUPACTIVELOCKEDCOL = (Hyprlang::CUSTOMTYPE* const*)g_pConfigManager->getConfigValuePtr("group:col.border_locked_active");
|
||||
static auto* const PGROUPINACTIVELOCKEDCOL = (Hyprlang::CUSTOMTYPE* const*)g_pConfigManager->getConfigValuePtr("group:col.border_locked_inactive");
|
||||
static auto* const PINACTIVEALPHA = (Hyprlang::FLOAT* const*)g_pConfigManager->getConfigValuePtr("decoration:inactive_opacity");
|
||||
static auto* const PACTIVEALPHA = (Hyprlang::FLOAT* const*)g_pConfigManager->getConfigValuePtr("decoration:active_opacity");
|
||||
static auto* const PFULLSCREENALPHA = (Hyprlang::FLOAT* const*)g_pConfigManager->getConfigValuePtr("decoration:fullscreen_opacity");
|
||||
static auto* const PSHADOWCOL = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("decoration:col.shadow");
|
||||
static auto* const PSHADOWCOLINACTIVE = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("decoration:col.shadow_inactive");
|
||||
static auto* const PDIMSTRENGTH = (Hyprlang::FLOAT* const*)g_pConfigManager->getConfigValuePtr("decoration:dim_strength");
|
||||
static auto* const PDIMENABLED = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("decoration:dim_inactive");
|
||||
|
||||
auto* const ACTIVECOL = (CGradientValueData*)(*PACTIVECOL)->getData();
|
||||
auto* const INACTIVECOL = (CGradientValueData*)(*PINACTIVECOL)->getData();
|
||||
auto* const NOGROUPACTIVECOL = (CGradientValueData*)(*PNOGROUPACTIVECOL)->getData();
|
||||
auto* const NOGROUPINACTIVECOL = (CGradientValueData*)(*PNOGROUPINACTIVECOL)->getData();
|
||||
auto* const GROUPACTIVECOL = (CGradientValueData*)(*PGROUPACTIVECOL)->getData();
|
||||
auto* const GROUPINACTIVECOL = (CGradientValueData*)(*PGROUPINACTIVECOL)->getData();
|
||||
auto* const GROUPACTIVELOCKEDCOL = (CGradientValueData*)(*PGROUPACTIVELOCKEDCOL)->getData();
|
||||
auto* const GROUPINACTIVELOCKEDCOL = (CGradientValueData*)(*PGROUPINACTIVELOCKEDCOL)->getData();
|
||||
|
||||
auto setBorderColor = [&](CGradientValueData grad) -> void {
|
||||
if (grad == pWindow->m_cRealBorderColor)
|
||||
|
@ -1896,31 +1944,31 @@ void CCompositor::updateWindowAnimatedDecorationValues(CWindow* pWindow) {
|
|||
// opacity
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID);
|
||||
if (pWindow->m_bIsFullscreen && PWORKSPACE->m_efFullscreenMode == FULLSCREEN_FULL) {
|
||||
pWindow->m_fActiveInactiveAlpha = *PFULLSCREENALPHA;
|
||||
pWindow->m_fActiveInactiveAlpha = **PFULLSCREENALPHA;
|
||||
} else {
|
||||
if (pWindow == m_pLastWindow)
|
||||
pWindow->m_fActiveInactiveAlpha = pWindow->m_sSpecialRenderData.alphaOverride.toUnderlying() ? pWindow->m_sSpecialRenderData.alpha.toUnderlying() :
|
||||
pWindow->m_sSpecialRenderData.alpha.toUnderlying() * *PACTIVEALPHA;
|
||||
pWindow->m_sSpecialRenderData.alpha.toUnderlying() * **PACTIVEALPHA;
|
||||
else
|
||||
pWindow->m_fActiveInactiveAlpha = pWindow->m_sSpecialRenderData.alphaInactive.toUnderlying() != -1 ?
|
||||
(pWindow->m_sSpecialRenderData.alphaInactiveOverride.toUnderlying() ? pWindow->m_sSpecialRenderData.alphaInactive.toUnderlying() :
|
||||
pWindow->m_sSpecialRenderData.alphaInactive.toUnderlying() * *PINACTIVEALPHA) :
|
||||
*PINACTIVEALPHA;
|
||||
pWindow->m_sSpecialRenderData.alphaInactive.toUnderlying() * **PINACTIVEALPHA) :
|
||||
**PINACTIVEALPHA;
|
||||
}
|
||||
|
||||
// dim
|
||||
if (pWindow == m_pLastWindow || pWindow->m_sAdditionalConfigData.forceNoDim || !*PDIMENABLED) {
|
||||
if (pWindow == m_pLastWindow || pWindow->m_sAdditionalConfigData.forceNoDim || !**PDIMENABLED) {
|
||||
pWindow->m_fDimPercent = 0;
|
||||
} else {
|
||||
pWindow->m_fDimPercent = *PDIMSTRENGTH;
|
||||
pWindow->m_fDimPercent = **PDIMSTRENGTH;
|
||||
}
|
||||
|
||||
// shadow
|
||||
if (pWindow->m_iX11Type != 2 && !pWindow->m_bX11DoesntWantBorders) {
|
||||
if (pWindow == m_pLastWindow) {
|
||||
pWindow->m_cRealShadowColor = CColor(*PSHADOWCOL);
|
||||
pWindow->m_cRealShadowColor = CColor(**PSHADOWCOL);
|
||||
} else {
|
||||
pWindow->m_cRealShadowColor = CColor(*PSHADOWCOLINACTIVE != INT_MAX ? *PSHADOWCOLINACTIVE : *PSHADOWCOL);
|
||||
pWindow->m_cRealShadowColor = CColor(**PSHADOWCOLINACTIVE != INT_MAX ? **PSHADOWCOLINACTIVE : **PSHADOWCOL);
|
||||
}
|
||||
} else {
|
||||
pWindow->m_cRealShadowColor.setValueAndWarp(CColor(0, 0, 0, 0)); // no shadow
|
||||
|
@ -1967,7 +2015,7 @@ void CCompositor::swapActiveWorkspaces(CMonitor* pMonitorA, CMonitor* pMonitorB)
|
|||
|
||||
// additionally, move floating and fs windows manually
|
||||
if (w->m_bIsFloating)
|
||||
w->m_vRealPosition = w->m_vRealPosition.vec() - pMonitorA->vecPosition + pMonitorB->vecPosition;
|
||||
w->m_vRealPosition = w->m_vRealPosition.value() - pMonitorA->vecPosition + pMonitorB->vecPosition;
|
||||
|
||||
if (w->m_bIsFullscreen) {
|
||||
w->m_vRealPosition = pMonitorB->vecPosition;
|
||||
|
@ -1992,7 +2040,7 @@ void CCompositor::swapActiveWorkspaces(CMonitor* pMonitorA, CMonitor* pMonitorB)
|
|||
|
||||
// additionally, move floating and fs windows manually
|
||||
if (w->m_bIsFloating)
|
||||
w->m_vRealPosition = w->m_vRealPosition.vec() - pMonitorB->vecPosition + pMonitorA->vecPosition;
|
||||
w->m_vRealPosition = w->m_vRealPosition.value() - pMonitorB->vecPosition + pMonitorA->vecPosition;
|
||||
|
||||
if (w->m_bIsFullscreen) {
|
||||
w->m_vRealPosition = pMonitorA->vecPosition;
|
||||
|
@ -2012,7 +2060,11 @@ void CCompositor::swapActiveWorkspaces(CMonitor* pMonitorA, CMonitor* pMonitorB)
|
|||
updateFullscreenFadeOnWorkspace(PWORKSPACEB);
|
||||
updateFullscreenFadeOnWorkspace(PWORKSPACEA);
|
||||
|
||||
g_pInputManager->sendMotionEventsToFocused();
|
||||
if (pMonitorA->ID == g_pCompositor->m_pLastMonitor->ID || pMonitorB->ID == g_pCompositor->m_pLastMonitor->ID) {
|
||||
const auto LASTWIN = pMonitorA->ID == g_pCompositor->m_pLastMonitor->ID ? PWORKSPACEB->getLastFocusedWindow() : PWORKSPACEA->getLastFocusedWindow();
|
||||
g_pCompositor->focusWindow(LASTWIN ? LASTWIN :
|
||||
(g_pCompositor->vectorToWindowUnified(g_pInputManager->getMouseCoordsInternal(), RESERVED_EXTENTS | INPUT_EXTENTS | ALLOW_FLOATING)));
|
||||
}
|
||||
|
||||
// event
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"moveworkspace", PWORKSPACEA->m_szName + "," + pMonitorB->szName});
|
||||
|
@ -2022,7 +2074,11 @@ void CCompositor::swapActiveWorkspaces(CMonitor* pMonitorA, CMonitor* pMonitorB)
|
|||
}
|
||||
|
||||
CMonitor* CCompositor::getMonitorFromString(const std::string& name) {
|
||||
if (name[0] == '+' || name[0] == '-') {
|
||||
if (name == "current")
|
||||
return g_pCompositor->m_pLastMonitor;
|
||||
else if (isDirection(name))
|
||||
return getMonitorInDirection(name[0]);
|
||||
else if (name[0] == '+' || name[0] == '-') {
|
||||
// relative
|
||||
|
||||
if (m_vMonitors.size() == 1)
|
||||
|
@ -2077,39 +2133,21 @@ CMonitor* CCompositor::getMonitorFromString(const std::string& name) {
|
|||
Debug::log(ERR, "Error in getMonitorFromString: invalid arg 1");
|
||||
return nullptr;
|
||||
}
|
||||
} else if (name.starts_with("desc:")) {
|
||||
const auto DESCRIPTION = name.substr(5);
|
||||
|
||||
} else {
|
||||
for (auto& m : m_vMonitors) {
|
||||
if (!m->output)
|
||||
continue;
|
||||
|
||||
if (m->szDescription.starts_with(DESCRIPTION)) {
|
||||
if (m->matchesStaticSelector(name)) {
|
||||
return m.get();
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
} else {
|
||||
if (name == "current")
|
||||
return g_pCompositor->m_pLastMonitor;
|
||||
|
||||
if (isDirection(name)) {
|
||||
const auto PMONITOR = getMonitorInDirection(name[0]);
|
||||
return PMONITOR;
|
||||
} else {
|
||||
for (auto& m : m_vMonitors) {
|
||||
if (m->szName == name) {
|
||||
return m.get();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void CCompositor::moveWorkspaceToMonitor(CWorkspace* pWorkspace, CMonitor* pMonitor) {
|
||||
void CCompositor::moveWorkspaceToMonitor(CWorkspace* pWorkspace, CMonitor* pMonitor, bool noWarpCursor) {
|
||||
|
||||
// We trust the workspace and monitor to be correct.
|
||||
|
||||
|
@ -2124,7 +2162,7 @@ void CCompositor::moveWorkspaceToMonitor(CWorkspace* pWorkspace, CMonitor* pMoni
|
|||
|
||||
// fix old mon
|
||||
int nextWorkspaceOnMonitorID = -1;
|
||||
if (!SWITCHINGISACTIVE)
|
||||
if (!SWITCHINGISACTIVE || !POLDMON)
|
||||
nextWorkspaceOnMonitorID = pWorkspace->m_iID;
|
||||
else {
|
||||
for (auto& w : m_vWorkspaces) {
|
||||
|
@ -2149,7 +2187,7 @@ void CCompositor::moveWorkspaceToMonitor(CWorkspace* pWorkspace, CMonitor* pMoni
|
|||
}
|
||||
|
||||
Debug::log(LOG, "moveWorkspaceToMonitor: Plugging gap with existing {}", nextWorkspaceOnMonitorID);
|
||||
POLDMON->changeWorkspace(nextWorkspaceOnMonitorID);
|
||||
POLDMON->changeWorkspace(nextWorkspaceOnMonitorID, false, true, true);
|
||||
}
|
||||
|
||||
// move the workspace
|
||||
|
@ -2169,14 +2207,14 @@ void CCompositor::moveWorkspaceToMonitor(CWorkspace* pWorkspace, CMonitor* pMoni
|
|||
if (w->m_bIsMapped && !w->isHidden()) {
|
||||
if (POLDMON) {
|
||||
if (w->m_bIsFloating)
|
||||
w->m_vRealPosition = w->m_vRealPosition.vec() - POLDMON->vecPosition + pMonitor->vecPosition;
|
||||
w->m_vRealPosition = w->m_vRealPosition.value() - POLDMON->vecPosition + pMonitor->vecPosition;
|
||||
|
||||
if (w->m_bIsFullscreen) {
|
||||
w->m_vRealPosition = pMonitor->vecPosition;
|
||||
w->m_vRealSize = pMonitor->vecSize;
|
||||
}
|
||||
} else {
|
||||
w->m_vRealPosition = Vector2D{(int)w->m_vRealPosition.goalv().x % (int)pMonitor->vecSize.x, (int)w->m_vRealPosition.goalv().y % (int)pMonitor->vecSize.y};
|
||||
w->m_vRealPosition = Vector2D{(int)w->m_vRealPosition.goal().x % (int)pMonitor->vecSize.x, (int)w->m_vRealPosition.goal().y % (int)pMonitor->vecSize.y};
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2190,11 +2228,13 @@ void CCompositor::moveWorkspaceToMonitor(CWorkspace* pWorkspace, CMonitor* pMoni
|
|||
if (const auto PWORKSPACE = getWorkspaceByID(pMonitor->activeWorkspace); PWORKSPACE)
|
||||
getWorkspaceByID(pMonitor->activeWorkspace)->startAnim(false, false);
|
||||
|
||||
setActiveMonitor(pMonitor);
|
||||
pMonitor->activeWorkspace = pWorkspace->m_iID;
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(pMonitor->ID);
|
||||
|
||||
pWorkspace->startAnim(true, true, true);
|
||||
|
||||
if (!noWarpCursor)
|
||||
wlr_cursor_warp(m_sWLRCursor, nullptr, pMonitor->vecPosition.x + pMonitor->vecTransformedSize.x / 2, pMonitor->vecPosition.y + pMonitor->vecTransformedSize.y / 2);
|
||||
|
||||
g_pInputManager->sendMotionEventsToFocused();
|
||||
|
@ -2282,7 +2322,6 @@ void CCompositor::setWindowFullscreen(CWindow* pWindow, bool on, eFullscreenMode
|
|||
|
||||
g_pXWaylandManager->setWindowFullscreen(pWindow, pWindow->shouldSendFullscreenState());
|
||||
|
||||
pWindow->updateDynamicRules();
|
||||
updateWindowAnimatedDecorationValues(pWindow);
|
||||
|
||||
// make all windows on the same workspace under the fullscreen window
|
||||
|
@ -2292,7 +2331,7 @@ void CCompositor::setWindowFullscreen(CWindow* pWindow, bool on, eFullscreenMode
|
|||
}
|
||||
updateFullscreenFadeOnWorkspace(PWORKSPACE);
|
||||
|
||||
g_pXWaylandManager->setWindowSize(pWindow, pWindow->m_vRealSize.goalv(), true);
|
||||
g_pXWaylandManager->setWindowSize(pWindow, pWindow->m_vRealSize.goal(), true);
|
||||
|
||||
forceReportSizesToWindowsOnWorkspace(pWindow->m_iWorkspaceID);
|
||||
|
||||
|
@ -2415,9 +2454,9 @@ void CCompositor::warpCursorTo(const Vector2D& pos, bool force) {
|
|||
// warpCursorTo should only be used for warps that
|
||||
// should be disabled with no_cursor_warps
|
||||
|
||||
static auto* const PNOWARPS = &g_pConfigManager->getConfigValuePtr("general:no_cursor_warps")->intValue;
|
||||
static auto* const PNOWARPS = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("general:no_cursor_warps");
|
||||
|
||||
if (*PNOWARPS && !force)
|
||||
if (**PNOWARPS && !force)
|
||||
return;
|
||||
|
||||
if (!m_sSeat.mouse)
|
||||
|
@ -2531,7 +2570,7 @@ Vector2D CCompositor::parseWindowVectorArgsRelative(const std::string& args, con
|
|||
void CCompositor::forceReportSizesToWindowsOnWorkspace(const int& wid) {
|
||||
for (auto& w : m_vWindows) {
|
||||
if (w->m_iWorkspaceID == wid && w->m_bIsMapped && !w->isHidden()) {
|
||||
g_pXWaylandManager->setWindowSize(w.get(), w->m_vRealSize.vec(), true);
|
||||
g_pXWaylandManager->setWindowSize(w.get(), w->m_vRealSize.value(), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2583,7 +2622,7 @@ void CCompositor::setActiveMonitor(CMonitor* pMonitor) {
|
|||
|
||||
const auto PWORKSPACE = getWorkspaceByID(pMonitor->activeWorkspace);
|
||||
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"focusedmon", pMonitor->szName + "," + PWORKSPACE->m_szName});
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"focusedmon", pMonitor->szName + "," + (PWORKSPACE ? PWORKSPACE->m_szName : "?")});
|
||||
EMIT_HOOK_EVENT("focusedMon", pMonitor);
|
||||
m_pLastMonitor = pMonitor;
|
||||
}
|
||||
|
@ -2604,11 +2643,7 @@ int CCompositor::getNewSpecialID() {
|
|||
}
|
||||
|
||||
void CCompositor::performUserChecks() {
|
||||
if (g_pConfigManager->getInt("general:allow_tearing") == 1 && !envEnabled("WLR_DRM_NO_ATOMIC")) {
|
||||
g_pHyprNotificationOverlay->addNotification("You have enabled tearing, but immediate presentations are not available on your configuration. Try adding "
|
||||
"env = WLR_DRM_NO_ATOMIC,1 to your config.",
|
||||
CColor(0), 15000, ICON_WARNING);
|
||||
}
|
||||
; // intentional
|
||||
}
|
||||
|
||||
void CCompositor::moveWindowToWorkspaceSafe(CWindow* pWindow, CWorkspace* pWorkspace) {
|
||||
|
@ -2636,7 +2671,7 @@ void CCompositor::moveWindowToWorkspaceSafe(CWindow* pWindow, CWorkspace* pWorks
|
|||
g_pLayoutManager->getCurrentLayout()->onWindowCreatedTiling(pWindow);
|
||||
} else {
|
||||
const auto PWINDOWMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID);
|
||||
const auto POSTOMON = pWindow->m_vRealPosition.goalv() - PWINDOWMONITOR->vecPosition;
|
||||
const auto POSTOMON = pWindow->m_vRealPosition.goal() - PWINDOWMONITOR->vecPosition;
|
||||
|
||||
const auto PWORKSPACEMONITOR = g_pCompositor->getMonitorFromID(pWorkspace->m_iMonitorID);
|
||||
|
||||
|
@ -2684,7 +2719,7 @@ void CCompositor::setIdleActivityInhibit(bool enabled) {
|
|||
wlr_idle_notifier_v1_set_inhibited(g_pCompositor->m_sWLRIdleNotifier, !enabled);
|
||||
}
|
||||
void CCompositor::arrangeMonitors() {
|
||||
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");
|
||||
|
||||
std::vector<CMonitor*> toArrange;
|
||||
std::vector<CMonitor*> arranged;
|
||||
|
@ -2733,9 +2768,9 @@ void CCompositor::arrangeMonitors() {
|
|||
for (auto& m : m_vMonitors) {
|
||||
Debug::log(LOG, "arrangeMonitors: {} xwayland [{}, {:.2f}]", m->szName, maxOffset, 0.f);
|
||||
m->vecXWaylandPosition = {maxOffset, 0};
|
||||
maxOffset += (*PXWLFORCESCALEZERO ? m->vecTransformedSize.x : m->vecSize.x);
|
||||
maxOffset += (**PXWLFORCESCALEZERO ? m->vecTransformedSize.x : m->vecSize.x);
|
||||
|
||||
if (*PXWLFORCESCALEZERO)
|
||||
if (**PXWLFORCESCALEZERO)
|
||||
m->xwaylandScale = m->scale;
|
||||
else
|
||||
m->xwaylandScale = 1.f;
|
||||
|
@ -2783,10 +2818,27 @@ void CCompositor::leaveUnsafeState() {
|
|||
void CCompositor::setPreferredScaleForSurface(wlr_surface* pSurface, double scale) {
|
||||
g_pProtocolManager->m_pFractionalScaleProtocolManager->setPreferredScaleForSurface(pSurface, scale);
|
||||
wlr_surface_set_preferred_buffer_scale(pSurface, static_cast<int32_t>(std::ceil(scale)));
|
||||
|
||||
const auto PSURFACE = CWLSurface::surfaceFromWlr(pSurface);
|
||||
if (!PSURFACE) {
|
||||
Debug::log(WARN, "Orphaned wlr_surface {:x} in setPreferredScaleForSurface", (uintptr_t)pSurface);
|
||||
return;
|
||||
}
|
||||
|
||||
PSURFACE->m_fLastScale = scale;
|
||||
PSURFACE->m_iLastScale = static_cast<int32_t>(std::ceil(scale));
|
||||
}
|
||||
|
||||
void CCompositor::setPreferredTransformForSurface(wlr_surface* pSurface, wl_output_transform transform) {
|
||||
wlr_surface_set_preferred_buffer_transform(pSurface, transform);
|
||||
|
||||
const auto PSURFACE = CWLSurface::surfaceFromWlr(pSurface);
|
||||
if (!PSURFACE) {
|
||||
Debug::log(WARN, "Orphaned wlr_surface {:x} in setPreferredTransformForSurface", (uintptr_t)pSurface);
|
||||
return;
|
||||
}
|
||||
|
||||
PSURFACE->m_eLastTransform = transform;
|
||||
}
|
||||
|
||||
void CCompositor::updateSuspendedStates() {
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
#include "debug/HyprDebugOverlay.hpp"
|
||||
#include "debug/HyprNotificationOverlay.hpp"
|
||||
#include "helpers/Monitor.hpp"
|
||||
#include "helpers/Workspace.hpp"
|
||||
#include "desktop/Workspace.hpp"
|
||||
#include "Window.hpp"
|
||||
#include "render/Renderer.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_vRealMonitors; // for all monitors, even those turned off
|
||||
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<SSubsurface>> m_vSubsurfaces;
|
||||
std::vector<CWindow*> m_vWindowsFadingOut;
|
||||
std::vector<SLayerSurface*> m_vSurfacesFadingOut;
|
||||
|
||||
|
@ -135,16 +133,14 @@ class CCompositor {
|
|||
void focusSurface(wlr_surface*, CWindow* pWindowOwner = nullptr);
|
||||
bool windowExists(CWindow*);
|
||||
bool windowValidMapped(CWindow*);
|
||||
CWindow* vectorToWindowIdeal(const Vector2D&, CWindow* pIgnoreWindow = nullptr); // used only for finding a window to focus on, basically a "findFocusableWindow"
|
||||
CWindow* vectorToWindowTiled(const Vector2D&);
|
||||
bool monitorExists(CMonitor*);
|
||||
CWindow* vectorToWindowUnified(const Vector2D&, uint8_t properties, CWindow* pIgnoreWindow = nullptr);
|
||||
wlr_surface* vectorToLayerSurface(const Vector2D&, std::vector<std::unique_ptr<SLayerSurface>>*, Vector2D*, SLayerSurface**);
|
||||
SIMEPopup* vectorToIMEPopup(const Vector2D& pos, std::list<SIMEPopup>& popups);
|
||||
wlr_surface* vectorWindowToSurface(const Vector2D&, CWindow*, Vector2D& sl);
|
||||
Vector2D vectorToSurfaceLocal(const Vector2D&, CWindow*, wlr_surface*);
|
||||
CWindow* windowFromCursor();
|
||||
CWindow* windowFloatingFromCursor();
|
||||
CMonitor* getMonitorFromOutput(wlr_output*);
|
||||
CWindow* getWindowForPopup(wlr_xdg_popup*);
|
||||
CMonitor* getRealMonitorFromOutput(wlr_output*);
|
||||
CWindow* getWindowFromSurface(wlr_surface*);
|
||||
CWindow* getWindowFromHandle(uint32_t);
|
||||
CWindow* getWindowFromZWLRHandle(wl_resource*);
|
||||
|
@ -172,11 +168,12 @@ class CCompositor {
|
|||
bool isPointOnReservedArea(const Vector2D& point, const CMonitor* monitor = nullptr);
|
||||
CWindow* getConstraintWindow(SMouse*);
|
||||
CMonitor* getMonitorInDirection(const char&);
|
||||
CMonitor* getMonitorInDirection(CMonitor*, const char&);
|
||||
void updateAllWindowsAnimatedDecorationValues();
|
||||
void updateWorkspaceWindows(const int64_t& id);
|
||||
void updateWindowAnimatedDecorationValues(CWindow*);
|
||||
int getNextAvailableMonitorID(std::string const& name);
|
||||
void moveWorkspaceToMonitor(CWorkspace*, CMonitor*);
|
||||
void moveWorkspaceToMonitor(CWorkspace*, CMonitor*, bool noWarpCursor = false);
|
||||
void swapActiveWorkspaces(CMonitor*, CMonitor*);
|
||||
CMonitor* getMonitorFromString(const std::string&);
|
||||
bool workspaceIDOutOfBounds(const int64_t&);
|
||||
|
@ -214,6 +211,7 @@ class CCompositor {
|
|||
|
||||
private:
|
||||
void initAllSignals();
|
||||
void removeAllSignals();
|
||||
void setRandomSplash();
|
||||
void initManagers(eManagersInitStage stage);
|
||||
void prepareFallbackOutput();
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "helpers/Vector2D.hpp"
|
||||
#include <functional>
|
||||
|
||||
enum eIcons {
|
||||
ICON_WARNING = 0,
|
||||
|
@ -52,4 +53,20 @@ struct SWindowDecorationExtents {
|
|||
bool operator==(const SWindowDecorationExtents& other) const {
|
||||
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;
|
||||
};
|
165
src/Window.cpp
|
@ -5,14 +5,14 @@
|
|||
#include "render/decorations/CHyprBorderDecoration.hpp"
|
||||
|
||||
CWindow::CWindow() {
|
||||
m_vRealPosition.create(AVARTYPE_VECTOR, g_pConfigManager->getAnimationPropertyConfig("windowsIn"), (void*)this, AVARDAMAGE_ENTIRE);
|
||||
m_vRealSize.create(AVARTYPE_VECTOR, g_pConfigManager->getAnimationPropertyConfig("windowsIn"), (void*)this, AVARDAMAGE_ENTIRE);
|
||||
m_fBorderFadeAnimationProgress.create(AVARTYPE_FLOAT, g_pConfigManager->getAnimationPropertyConfig("border"), (void*)this, AVARDAMAGE_BORDER);
|
||||
m_fBorderAngleAnimationProgress.create(AVARTYPE_FLOAT, g_pConfigManager->getAnimationPropertyConfig("borderangle"), (void*)this, AVARDAMAGE_BORDER);
|
||||
m_fAlpha.create(AVARTYPE_FLOAT, g_pConfigManager->getAnimationPropertyConfig("fadeIn"), (void*)this, AVARDAMAGE_ENTIRE);
|
||||
m_fActiveInactiveAlpha.create(AVARTYPE_FLOAT, g_pConfigManager->getAnimationPropertyConfig("fadeSwitch"), (void*)this, AVARDAMAGE_ENTIRE);
|
||||
m_cRealShadowColor.create(AVARTYPE_COLOR, g_pConfigManager->getAnimationPropertyConfig("fadeShadow"), (void*)this, AVARDAMAGE_SHADOW);
|
||||
m_fDimPercent.create(AVARTYPE_FLOAT, g_pConfigManager->getAnimationPropertyConfig("fadeDim"), (void*)this, AVARDAMAGE_ENTIRE);
|
||||
m_vRealPosition.create(g_pConfigManager->getAnimationPropertyConfig("windowsIn"), (void*)this, AVARDAMAGE_ENTIRE);
|
||||
m_vRealSize.create(g_pConfigManager->getAnimationPropertyConfig("windowsIn"), (void*)this, AVARDAMAGE_ENTIRE);
|
||||
m_fBorderFadeAnimationProgress.create(g_pConfigManager->getAnimationPropertyConfig("border"), (void*)this, AVARDAMAGE_BORDER);
|
||||
m_fBorderAngleAnimationProgress.create(g_pConfigManager->getAnimationPropertyConfig("borderangle"), (void*)this, AVARDAMAGE_BORDER);
|
||||
m_fAlpha.create(g_pConfigManager->getAnimationPropertyConfig("fadeIn"), (void*)this, AVARDAMAGE_ENTIRE);
|
||||
m_fActiveInactiveAlpha.create(g_pConfigManager->getAnimationPropertyConfig("fadeSwitch"), (void*)this, AVARDAMAGE_ENTIRE);
|
||||
m_cRealShadowColor.create(g_pConfigManager->getAnimationPropertyConfig("fadeShadow"), (void*)this, AVARDAMAGE_SHADOW);
|
||||
m_fDimPercent.create(g_pConfigManager->getAnimationPropertyConfig("fadeDim"), (void*)this, AVARDAMAGE_ENTIRE);
|
||||
|
||||
addWindowDeco(std::make_unique<CHyprDropShadowDecoration>(this));
|
||||
addWindowDeco(std::make_unique<CHyprBorderDecoration>(this));
|
||||
|
@ -39,8 +39,8 @@ SWindowDecorationExtents CWindow::getFullWindowExtents() {
|
|||
|
||||
if (m_sAdditionalConfigData.dimAround) {
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
|
||||
return {{m_vRealPosition.vec().x - PMONITOR->vecPosition.x, m_vRealPosition.vec().y - PMONITOR->vecPosition.y},
|
||||
{PMONITOR->vecSize.x - (m_vRealPosition.vec().x - PMONITOR->vecPosition.x), PMONITOR->vecSize.y - (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.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}};
|
||||
|
@ -101,8 +101,8 @@ CBox CWindow::getFullWindowBoundingBox() {
|
|||
|
||||
auto maxExtents = getFullWindowExtents();
|
||||
|
||||
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};
|
||||
CBox finalBox = {m_vRealPosition.value().x - maxExtents.topLeft.x, m_vRealPosition.value().y - maxExtents.topLeft.y,
|
||||
m_vRealSize.value().x + maxExtents.topLeft.x + maxExtents.bottomRight.x, m_vRealSize.value().y + maxExtents.topLeft.y + maxExtents.bottomRight.y};
|
||||
|
||||
return finalBox;
|
||||
}
|
||||
|
@ -139,39 +139,29 @@ CBox CWindow::getWindowIdealBoundingBoxIgnoreReserved() {
|
|||
return CBox{(int)POS.x, (int)POS.y, (int)SIZE.x, (int)SIZE.y};
|
||||
}
|
||||
|
||||
CBox CWindow::getWindowInputBox() {
|
||||
const int BORDERSIZE = getRealBorderSize();
|
||||
CBox CWindow::getWindowBoxUnified(uint64_t properties) {
|
||||
|
||||
if (m_sAdditionalConfigData.dimAround) {
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
|
||||
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)
|
||||
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;
|
||||
return box;
|
||||
}
|
||||
|
||||
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() {
|
||||
|
@ -318,7 +308,7 @@ void CWindow::destroyToplevelHandle() {
|
|||
}
|
||||
|
||||
void CWindow::updateToplevel() {
|
||||
updateSurfaceOutputs();
|
||||
updateSurfaceScaleTransformDetails();
|
||||
|
||||
if (!m_phForeignToplevel)
|
||||
return;
|
||||
|
@ -345,8 +335,8 @@ void sendLeaveIter(wlr_surface* pSurface, int x, int y, void* data) {
|
|||
wlr_surface_send_leave(pSurface, OUTPUT);
|
||||
}
|
||||
|
||||
void CWindow::updateSurfaceOutputs() {
|
||||
if (m_iLastSurfaceMonitorID == m_iMonitorID || !m_bIsMapped || m_bHidden)
|
||||
void CWindow::updateSurfaceScaleTransformDetails() {
|
||||
if (!m_bIsMapped || m_bHidden)
|
||||
return;
|
||||
|
||||
const auto PLASTMONITOR = g_pCompositor->getMonitorFromID(m_iLastSurfaceMonitorID);
|
||||
|
@ -355,16 +345,23 @@ void CWindow::updateSurfaceOutputs() {
|
|||
|
||||
const auto PNEWMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
|
||||
|
||||
if (PNEWMONITOR != PLASTMONITOR) {
|
||||
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(),
|
||||
[](wlr_surface* surf, int x, int y, void* data) {
|
||||
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);
|
||||
},
|
||||
this);
|
||||
|
@ -374,7 +371,7 @@ void CWindow::moveToWorkspace(int workspaceID) {
|
|||
if (m_iWorkspaceID == workspaceID)
|
||||
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;
|
||||
|
||||
|
@ -395,9 +392,9 @@ void CWindow::moveToWorkspace(int workspaceID) {
|
|||
}
|
||||
|
||||
// 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);
|
||||
|
||||
if (PWS) {
|
||||
|
@ -436,11 +433,11 @@ void CWindow::removeDecorationByType(eDecorationType type) {
|
|||
}
|
||||
|
||||
void unregisterVar(void* ptr) {
|
||||
((CAnimatedVariable*)ptr)->unregister();
|
||||
((CBaseAnimatedVariable*)ptr)->unregister();
|
||||
}
|
||||
|
||||
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)
|
||||
g_pCompositor->m_pLastWindow = nullptr;
|
||||
|
@ -462,7 +459,7 @@ void CWindow::onUnmap() {
|
|||
|
||||
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);
|
||||
if (PMONITOR && PMONITOR->specialWorkspaceID == m_iWorkspaceID)
|
||||
PMONITOR->setSpecialWorkspace(nullptr);
|
||||
|
@ -474,12 +471,17 @@ void CWindow::onUnmap() {
|
|||
PMONITOR->solitaryClient = nullptr;
|
||||
|
||||
g_pCompositor->updateWorkspaceWindows(m_iWorkspaceID);
|
||||
|
||||
if (m_bIsX11)
|
||||
return;
|
||||
|
||||
m_pSubsurfaceHead.reset();
|
||||
m_pPopupHead.reset();
|
||||
}
|
||||
|
||||
void CWindow::onMap() {
|
||||
|
||||
m_pWLSurface.assign(g_pXWaylandManager->getWindowSurface(this));
|
||||
m_pWLSurface.m_pOwner = this;
|
||||
m_pWLSurface.assign(g_pXWaylandManager->getWindowSurface(this), 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)
|
||||
m_vRealPosition.resetAllCallbacks();
|
||||
|
@ -511,10 +513,24 @@ void CWindow::onMap() {
|
|||
"CWindow");
|
||||
|
||||
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) {
|
||||
const auto PANIMVAR = (CAnimatedVariable*)ptr;
|
||||
const auto PANIMVAR = (CAnimatedVariable<float>*)ptr;
|
||||
|
||||
const std::string STYLE = PANIMVAR->getConfig()->pValues->internalStyle;
|
||||
|
||||
|
@ -625,23 +641,22 @@ void CWindow::applyDynamicRule(const SWindowRule& r) {
|
|||
if (active && token.contains("deg")) {
|
||||
activeBorderGradient.m_fAngle = std::stoi(token.substr(0, token.size() - 3)) * (PI / 180.0);
|
||||
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);
|
||||
} else if (active) {
|
||||
else if (active)
|
||||
activeBorderGradient.m_vColors.push_back(configStringToInt(token));
|
||||
} else {
|
||||
else
|
||||
inactiveBorderGradient.m_vColors.push_back(configStringToInt(token));
|
||||
}
|
||||
}
|
||||
|
||||
// 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);
|
||||
} else if (activeBorderGradient.m_vColors.empty()) {
|
||||
else if (activeBorderGradient.m_vColors.empty())
|
||||
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;
|
||||
} else {
|
||||
else {
|
||||
m_sSpecialRenderData.activeBorderColor = activeBorderGradient;
|
||||
m_sSpecialRenderData.inactiveBorderColor = inactiveBorderGradient;
|
||||
}
|
||||
|
@ -712,10 +727,10 @@ bool CWindow::isInCurvedCorner(double x, double y) {
|
|||
return false;
|
||||
|
||||
// (x0, y0), (x0, y1), ... are the center point of rounding at each corner
|
||||
double x0 = m_vRealPosition.vec().x + ROUNDING;
|
||||
double y0 = m_vRealPosition.vec().y + ROUNDING;
|
||||
double x1 = m_vRealPosition.vec().x + m_vRealSize.vec().x - ROUNDING;
|
||||
double y1 = m_vRealPosition.vec().y + m_vRealSize.vec().y - ROUNDING;
|
||||
double x0 = m_vRealPosition.value().x + ROUNDING;
|
||||
double y0 = m_vRealPosition.value().y + ROUNDING;
|
||||
double x1 = m_vRealPosition.value().x + m_vRealSize.value().x - ROUNDING;
|
||||
double y1 = m_vRealPosition.value().y + m_vRealSize.value().y - ROUNDING;
|
||||
|
||||
if (x < x0 && y < y0) {
|
||||
return Vector2D{x0, y0}.distance(Vector2D{x, y}) > (double)ROUNDING;
|
||||
|
@ -748,7 +763,7 @@ bool CWindow::hasPopupAt(const Vector2D& pos) {
|
|||
return false;
|
||||
|
||||
wlr_surface* resultSurf = nullptr;
|
||||
Vector2D origin = m_vRealPosition.vec();
|
||||
Vector2D origin = m_vRealPosition.value();
|
||||
SExtensionFindingData data = {origin, pos, &resultSurf};
|
||||
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 auto WORKSPACE = g_pCompositor->getWorkspaceByID(PCURRENT->m_iWorkspaceID);
|
||||
|
||||
const auto PWINDOWSIZE = PCURRENT->m_vRealSize.goalv();
|
||||
const auto PWINDOWPOS = PCURRENT->m_vRealPosition.goalv();
|
||||
const auto PWINDOWSIZE = PCURRENT->m_vRealSize.goal();
|
||||
const auto PWINDOWPOS = PCURRENT->m_vRealPosition.goal();
|
||||
|
||||
const auto CURRENTISFOCUS = PCURRENT == g_pCompositor->m_pLastWindow;
|
||||
|
||||
|
@ -982,19 +997,19 @@ void CWindow::updateGroupOutputs() {
|
|||
curr->m_iMonitorID = m_iMonitorID;
|
||||
curr->moveToWorkspace(m_iWorkspaceID);
|
||||
|
||||
curr->m_vRealPosition = m_vRealPosition.goalv();
|
||||
curr->m_vRealSize = m_vRealSize.goalv();
|
||||
curr->m_vRealPosition = m_vRealPosition.goal();
|
||||
curr->m_vRealSize = m_vRealSize.goal();
|
||||
|
||||
curr = curr->m_sGroupData.pNextWindow;
|
||||
}
|
||||
}
|
||||
|
||||
Vector2D CWindow::middle() {
|
||||
return m_vRealPosition.goalv() + m_vRealSize.goalv() / 2.f;
|
||||
return m_vRealPosition.goal() + m_vRealSize.goal() / 2.f;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(m_iWorkspaceID);
|
||||
|
@ -1002,7 +1017,7 @@ bool CWindow::opaque() {
|
|||
if (m_pWLSurface.small() && !m_pWLSurface.m_bFillIgnoreSmall)
|
||||
return false;
|
||||
|
||||
if (PWORKSPACE->m_fAlpha.fl() != 1.f)
|
||||
if (PWORKSPACE->m_fAlpha.value() != 1.f)
|
||||
return false;
|
||||
|
||||
if (m_bIsX11)
|
||||
|
@ -1019,9 +1034,9 @@ bool CWindow::opaque() {
|
|||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -1031,7 +1046,9 @@ void CWindow::updateSpecialRenderData() {
|
|||
const auto WORKSPACERULE = PWORKSPACE ? g_pConfigManager->getWorkspaceRuleFor(PWORKSPACE) : SWorkspaceRule{};
|
||||
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;
|
||||
|
||||
m_sSpecialRenderData.border = WORKSPACERULE.border.value_or(border);
|
||||
|
@ -1051,16 +1068,18 @@ int CWindow::getRealBorderSize() {
|
|||
if (m_sSpecialRenderData.borderSize.toUnderlying() != -1)
|
||||
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() {
|
||||
return (m_sAdditionalConfigData.forceTearing.toUnderlying() || m_bTearingHint) && g_pHyprRenderer->m_bTearingEnvSatisfied;
|
||||
return (m_sAdditionalConfigData.forceTearing.toUnderlying() || m_bTearingHint);
|
||||
}
|
||||
|
||||
bool CWindow::shouldSendFullscreenState() {
|
||||
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) {
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
#pragma once
|
||||
|
||||
#include "defines.hpp"
|
||||
#include "helpers/SubsurfaceTree.hpp"
|
||||
#include "desktop/Subsurface.hpp"
|
||||
#include "helpers/AnimatedVariable.hpp"
|
||||
#include "render/decorations/IHyprWindowDecoration.hpp"
|
||||
#include <deque>
|
||||
#include "config/ConfigDataValues.hpp"
|
||||
#include "helpers/Vector2D.hpp"
|
||||
#include "helpers/WLSurface.hpp"
|
||||
#include "desktop/WLSurface.hpp"
|
||||
#include "desktop/Popup.hpp"
|
||||
#include "macros.hpp"
|
||||
#include "managers/XWaylandManager.hpp"
|
||||
|
||||
|
@ -30,6 +31,24 @@ enum eGroupRules {
|
|||
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;
|
||||
|
||||
template <typename T>
|
||||
|
@ -133,6 +152,7 @@ struct SWindowAdditionalConfigData {
|
|||
CWindowOverridableVar<bool> forceNoBorder = false;
|
||||
CWindowOverridableVar<bool> forceNoShadow = false;
|
||||
CWindowOverridableVar<bool> forceNoDim = false;
|
||||
CWindowOverridableVar<bool> noFocus = false;
|
||||
CWindowOverridableVar<bool> windowDanceCompat = false;
|
||||
CWindowOverridableVar<bool> noMaxSize = false;
|
||||
CWindowOverridableVar<bool> dimAround = false;
|
||||
|
@ -174,7 +194,6 @@ class CWindow {
|
|||
DYNLISTENER(setTitleWindow);
|
||||
DYNLISTENER(setGeometryX11U);
|
||||
DYNLISTENER(fullscreenWindow);
|
||||
DYNLISTENER(newPopupXDG);
|
||||
DYNLISTENER(requestMove);
|
||||
DYNLISTENER(requestMinimize);
|
||||
DYNLISTENER(requestMaximize);
|
||||
|
@ -191,7 +210,6 @@ class CWindow {
|
|||
// DYNLISTENER(newSubsurfaceWindow);
|
||||
|
||||
CWLSurface m_pWLSurface;
|
||||
std::list<CWLSurface> m_lPopupSurfaces;
|
||||
|
||||
union {
|
||||
wlr_xdg_surface* xdg;
|
||||
|
@ -203,8 +221,8 @@ class CWindow {
|
|||
Vector2D m_vSize = Vector2D(0, 0);
|
||||
|
||||
// this is the real position and size used to draw the thing
|
||||
CAnimatedVariable m_vRealPosition;
|
||||
CAnimatedVariable m_vRealSize;
|
||||
CAnimatedVariable<Vector2D> m_vRealPosition;
|
||||
CAnimatedVariable<Vector2D> m_vRealSize;
|
||||
|
||||
// for not spamming the protocols
|
||||
Vector2D m_vReportedPosition;
|
||||
|
@ -225,6 +243,7 @@ class CWindow {
|
|||
bool m_bIsFloating = false;
|
||||
bool m_bDraggingTiled = false; // for dragging around tiled windows
|
||||
bool m_bIsFullscreen = false;
|
||||
bool m_bDontSendFullscreen = false;
|
||||
bool m_bWasMaximized = false;
|
||||
uint64_t m_iMonitorID = -1;
|
||||
std::string m_szTitle = "";
|
||||
|
@ -250,24 +269,26 @@ class CWindow {
|
|||
//
|
||||
|
||||
// For nofocus
|
||||
bool m_bNoFocus = false;
|
||||
bool m_bNoInitialFocus = false;
|
||||
|
||||
// Fullscreen and Maximize
|
||||
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
|
||||
CGradientValueData m_cRealBorderColor = {0};
|
||||
CGradientValueData m_cRealBorderColorPrevious = {0};
|
||||
CAnimatedVariable m_fBorderFadeAnimationProgress;
|
||||
CAnimatedVariable m_fBorderAngleAnimationProgress;
|
||||
CAnimatedVariable<float> m_fBorderFadeAnimationProgress;
|
||||
CAnimatedVariable<float> m_fBorderAngleAnimationProgress;
|
||||
|
||||
// Fade in-out
|
||||
CAnimatedVariable m_fAlpha;
|
||||
CAnimatedVariable<float> m_fAlpha;
|
||||
bool m_bFadingOut = false;
|
||||
bool m_bReadyToDelete = false;
|
||||
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;
|
||||
|
||||
// for alpha
|
||||
CAnimatedVariable m_fActiveInactiveAlpha;
|
||||
CAnimatedVariable<float> m_fActiveInactiveAlpha;
|
||||
|
||||
// animated shadow color
|
||||
CAnimatedVariable m_cRealShadowColor;
|
||||
CAnimatedVariable<CColor> m_cRealShadowColor;
|
||||
|
||||
// animated tint
|
||||
CAnimatedVariable m_fDimPercent;
|
||||
CAnimatedVariable<float> m_fDimPercent;
|
||||
|
||||
// swallowing
|
||||
CWindow* m_pSwallowed = nullptr;
|
||||
|
@ -342,7 +363,7 @@ class CWindow {
|
|||
// methods
|
||||
CBox getFullWindowBoundingBox();
|
||||
SWindowDecorationExtents getFullWindowExtents();
|
||||
CBox getWindowInputBox();
|
||||
CBox getWindowBoxUnified(uint64_t props);
|
||||
CBox getWindowMainSurfaceBox();
|
||||
CBox getWindowIdealBoundingBoxIgnoreReserved();
|
||||
void addWindowDeco(std::unique_ptr<IHyprWindowDecoration> deco);
|
||||
|
@ -356,7 +377,7 @@ class CWindow {
|
|||
void createToplevelHandle();
|
||||
void destroyToplevelHandle();
|
||||
void updateToplevel();
|
||||
void updateSurfaceOutputs();
|
||||
void updateSurfaceScaleTransformDetails();
|
||||
void moveToWorkspace(int);
|
||||
CWindow* X11TransientFor();
|
||||
void onUnmap();
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
#pragma once
|
||||
#include "../defines.hpp"
|
||||
#include "../helpers/VarList.hpp"
|
||||
#include <vector>
|
||||
|
||||
enum eConfigValueDataTypes {
|
||||
CVD_TYPE_INVALID = -1,
|
||||
CVD_TYPE_GRADIENT = 0
|
||||
CVD_TYPE_GRADIENT = 0,
|
||||
CVD_TYPE_CSS_VALUE = 1
|
||||
};
|
||||
|
||||
class ICustomConfigValueData {
|
||||
|
@ -50,3 +52,55 @@ class CGradientValueData : public ICustomConfigValueData {
|
|||
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 "ConfigDataValues.hpp"
|
||||
|
||||
#include <hyprlang.hpp>
|
||||
|
||||
#define INITANIMCFG(name) animationConfig[name] = {}
|
||||
#define CREATEANIMCFG(name, parent) animationConfig[name] = {false, "", "", 0.f, -1, &animationConfig["global"], &animationConfig[parent]}
|
||||
|
||||
#define HANDLE void*
|
||||
|
||||
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 {
|
||||
std::string monitor = "";
|
||||
std::string workspaceString = "";
|
||||
|
@ -43,14 +35,15 @@ struct SWorkspaceRule {
|
|||
int workspaceId = -1;
|
||||
bool isDefault = false;
|
||||
bool isPersistent = false;
|
||||
std::optional<int64_t> gapsIn;
|
||||
std::optional<int64_t> gapsOut;
|
||||
std::optional<CCssGapData> gapsIn;
|
||||
std::optional<CCssGapData> gapsOut;
|
||||
std::optional<int64_t> borderSize;
|
||||
std::optional<int> border;
|
||||
std::optional<int> rounding;
|
||||
std::optional<int> decorate;
|
||||
std::optional<int> shadow;
|
||||
std::optional<std::string> onCreatedEmptyRunCmd;
|
||||
std::optional<std::string> defaultName;
|
||||
std::map<std::string, std::string> layoutopts;
|
||||
};
|
||||
|
||||
|
@ -76,7 +69,12 @@ struct SAnimationPropertyConfig {
|
|||
struct SPluginKeyword {
|
||||
HANDLE handle = 0;
|
||||
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 {
|
||||
|
@ -91,28 +89,21 @@ class CConfigManager {
|
|||
void tick();
|
||||
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 = "");
|
||||
float getDeviceFloat(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 = "");
|
||||
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&);
|
||||
|
||||
SConfigValue* getConfigValuePtr(const std::string&);
|
||||
SConfigValue* getConfigValuePtrSafe(const std::string&);
|
||||
void* const* getConfigValuePtr(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 getMainConfigPath();
|
||||
|
||||
SMonitorRule getMonitorRuleFor(const std::string&, const std::string& displayName = "");
|
||||
SMonitorRule getMonitorRuleFor(const CMonitor&);
|
||||
SWorkspaceRule getWorkspaceRuleFor(CWorkspace*);
|
||||
std::string getDefaultWorkspaceFor(const std::string&);
|
||||
|
||||
|
@ -120,15 +111,15 @@ class CConfigManager {
|
|||
std::string getBoundMonitorStringForWS(const std::string&);
|
||||
const std::deque<SWorkspaceRule>& getAllWorkspaceRules();
|
||||
|
||||
std::vector<SWindowRule> getMatchingRules(CWindow*);
|
||||
std::vector<SWindowRule> getMatchingRules(CWindow*, bool dynamic = true);
|
||||
std::vector<SLayerRule> getMatchingRules(SLayerSurface*);
|
||||
|
||||
std::unordered_map<std::string, SMonitorAdditionalReservedArea> m_mAdditionalReservedAreas;
|
||||
|
||||
std::unordered_map<std::string, SAnimationPropertyConfig> getAnimationConfig();
|
||||
|
||||
void addPluginConfigVar(HANDLE handle, const std::string& name, const SConfigValue& value);
|
||||
void addPluginKeyword(HANDLE handle, const std::string& name, std::function<void(const std::string& cmd, const std::string& val)> fun);
|
||||
void addPluginConfigVar(HANDLE handle, const std::string& name, const Hyprlang::CConfigValue& value);
|
||||
void addPluginKeyword(HANDLE handle, const std::string& name, Hyprlang::PCONFIGHANDLERFUNC fun, Hyprlang::SHandlerOptions opts = {});
|
||||
void removePluginConfig(HANDLE handle);
|
||||
|
||||
// no-op when done.
|
||||
|
@ -141,7 +132,7 @@ class CConfigManager {
|
|||
void ensureMonitorStatus();
|
||||
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&);
|
||||
|
||||
|
@ -151,28 +142,42 @@ class CConfigManager {
|
|||
|
||||
void handlePluginLoads();
|
||||
|
||||
// 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:
|
||||
std::unique_ptr<Hyprlang::CConfig> m_pConfig;
|
||||
|
||||
std::deque<std::string> configPaths; // stores all the config paths
|
||||
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::string currentCategory = ""; // For storing the category of the current item
|
||||
|
||||
std::string parseError = ""; // For storing a parse error to display later
|
||||
|
||||
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<std::string> m_vDeclaredPlugins;
|
||||
std::unordered_map<HANDLE, std::unique_ptr<std::unordered_map<std::string, SConfigValue>>> pluginConfigs; // stores plugin configs
|
||||
std::vector<SPluginKeyword> pluginKeywords;
|
||||
std::vector<SPluginVariable> pluginVariables;
|
||||
|
||||
bool isFirstLaunch = true; // For exec-once
|
||||
|
||||
|
@ -186,42 +191,16 @@ class CConfigManager {
|
|||
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
|
||||
void setDefaultVars();
|
||||
void setDefaultAnimationVars();
|
||||
void setDeviceDefaultVars(const std::string&);
|
||||
void populateEnvironment();
|
||||
|
||||
void setAnimForChildren(SAnimationPropertyConfig* const);
|
||||
void updateBlurredLS(const std::string&, const bool);
|
||||
|
||||
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&);
|
||||
void setDefaultAnimationVars();
|
||||
std::optional<std::string> resetHLConfig();
|
||||
std::optional<std::string> verifyConfigExists();
|
||||
void postConfigReload(const Hyprlang::CParseResult& result);
|
||||
void reload();
|
||||
};
|
||||
|
||||
inline std::unique_ptr<CConfigManager> g_pConfigManager;
|
||||
|
|
|
@ -4,9 +4,9 @@
|
|||
|
||||
inline const std::string AUTOCONFIG = R"#(
|
||||
# #######################################################################################
|
||||
AUTOGENERATED HYPR CONFIG.
|
||||
PLEASE USE THE CONFIG PROVIDED IN THE GIT REPO /examples/hypr.conf AND EDIT IT,
|
||||
OR EDIT THIS ONE ACCORDING TO THE WIKI INSTRUCTIONS.
|
||||
# AUTOGENERATED HYPR CONFIG.
|
||||
# PLEASE USE THE CONFIG PROVIDED IN THE GIT REPO /examples/hypr.conf AND EDIT IT,
|
||||
# OR EDIT THIS ONE ACCORDING TO THE WIKI INSTRUCTIONS.
|
||||
# #######################################################################################
|
||||
|
||||
#
|
||||
|
@ -51,7 +51,7 @@ input {
|
|||
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 {
|
||||
|
@ -119,12 +119,13 @@ gestures {
|
|||
|
||||
misc {
|
||||
# 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
|
||||
# See https://wiki.hyprland.org/Configuring/Keywords/#executing for more
|
||||
device:epic-mouse-v1 {
|
||||
device {
|
||||
name = epic-mouse-v1
|
||||
sensitivity = -0.5
|
||||
}
|
||||
|
||||
|
@ -133,7 +134,7 @@ device:epic-mouse-v1 {
|
|||
# Example windowrule v2
|
||||
# windowrulev2 = float,class:^(kitty)$,title:^(kitty)$
|
||||
# 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
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include <sys/utsname.h>
|
||||
#include <fstream>
|
||||
#include <signal.h>
|
||||
#include <link.h>
|
||||
|
||||
#include "../plugins/PluginSystem.hpp"
|
||||
|
||||
|
@ -105,21 +106,38 @@ void CrashReporter::createAndSaveCrash(int sig) {
|
|||
const auto FPATH = std::filesystem::canonical("/proc/self/exe");
|
||||
#endif
|
||||
|
||||
std::string addrs = "";
|
||||
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__
|
||||
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
|
||||
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
|
||||
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 += Debug::rollingLog;
|
||||
finalCrashReport += Debug::rollingLog.substr(Debug::rollingLog.find("\n") + 1);
|
||||
|
||||
const auto HOME = getenv("HOME");
|
||||
const auto CACHE_HOME = getenv("XDG_CACHE_HOME");
|
||||
|
@ -128,22 +146,19 @@ void CrashReporter::createAndSaveCrash(int sig) {
|
|||
return;
|
||||
|
||||
std::ofstream ofs;
|
||||
std::string path;
|
||||
if (!CACHE_HOME || std::string(CACHE_HOME).empty()) {
|
||||
if (!std::filesystem::exists(std::string(HOME) + "/.hyprland"))
|
||||
std::filesystem::create_directory(std::string(HOME) + "/.hyprland");
|
||||
std::string reportDir;
|
||||
|
||||
if (!CACHE_HOME || std::string(CACHE_HOME).empty())
|
||||
reportDir = std::string(HOME) + "/.cache/hyprland";
|
||||
else
|
||||
reportDir = std::string(CACHE_HOME) + "/hyprland";
|
||||
|
||||
if (!std::filesystem::exists(reportDir))
|
||||
std::filesystem::create_directory(reportDir);
|
||||
const auto path = reportDir + "/hyprlandCrashReport" + std::to_string(PID) + ".txt";
|
||||
|
||||
path = std::string(HOME) + "/.hyprland/hyprlandCrashReport" + std::to_string(PID) + ".txt";
|
||||
ofs.open(path, std::ios::trunc);
|
||||
|
||||
} else {
|
||||
if (!std::filesystem::exists(std::string(CACHE_HOME) + "/hyprland"))
|
||||
std::filesystem::create_directory(std::string(CACHE_HOME) + "/hyprland");
|
||||
|
||||
path = std::string(CACHE_HOME) + "/hyprland/hyprlandCrashReport" + std::to_string(PID) + ".txt";
|
||||
ofs.open(path, std::ios::trunc);
|
||||
}
|
||||
|
||||
ofs << finalCrashReport;
|
||||
|
||||
ofs.close();
|
||||
|
|
|
@ -7,12 +7,13 @@
|
|||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <sys/un.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <typeindex>
|
||||
|
||||
static void trimTrailingComma(std::string& str) {
|
||||
if (!str.empty() && str.back() == ',')
|
||||
|
@ -28,7 +29,7 @@ static std::string getWorkspaceNameFromSpecialID(const int workspaceID) {
|
|||
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, ' ');
|
||||
auto allMonitors = false;
|
||||
|
||||
|
@ -39,7 +40,7 @@ std::string monitorsRequest(std::string request, HyprCtl::eHyprCtlOutputFormat f
|
|||
allMonitors = true;
|
||||
|
||||
std::string result = "";
|
||||
if (format == HyprCtl::FORMAT_JSON) {
|
||||
if (format == eHyprCtlOutputFormat::FORMAT_JSON) {
|
||||
result += "[";
|
||||
|
||||
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": {},
|
||||
"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->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,
|
||||
|
@ -97,7 +98,7 @@ std::string monitorsRequest(std::string request, HyprCtl::eHyprCtlOutputFormat f
|
|||
"workspace: {} ({})\n\treserved: {} "
|
||||
"{} {} {}\n\tscale: {:.2f}\n\ttransform: "
|
||||
"{}\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->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,
|
||||
|
@ -109,8 +110,8 @@ std::string monitorsRequest(std::string request, HyprCtl::eHyprCtlOutputFormat f
|
|||
return result;
|
||||
}
|
||||
|
||||
static std::string getGroupedData(CWindow* w, HyprCtl::eHyprCtlOutputFormat format) {
|
||||
const bool isJson = format == HyprCtl::FORMAT_JSON;
|
||||
static std::string getGroupedData(CWindow* w, eHyprCtlOutputFormat format) {
|
||||
const bool isJson = format == eHyprCtlOutputFormat::FORMAT_JSON;
|
||||
if (!w->m_sGroupData.pNextWindow)
|
||||
return isJson ? "" : "0";
|
||||
|
||||
|
@ -133,7 +134,7 @@ static std::string getGroupedData(CWindow* w, HyprCtl::eHyprCtlOutputFormat form
|
|||
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 {
|
||||
for (size_t i = 0; i < g_pCompositor->m_vWindowFocusHistory.size(); ++i) {
|
||||
if (g_pCompositor->m_vWindowFocusHistory[i] == wnd)
|
||||
|
@ -142,7 +143,7 @@ static std::string getWindowData(CWindow* w, HyprCtl::eHyprCtlOutputFormat forma
|
|||
return -1;
|
||||
};
|
||||
|
||||
if (format == HyprCtl::FORMAT_JSON) {
|
||||
if (format == eHyprCtlOutputFormat::FORMAT_JSON) {
|
||||
return std::format(
|
||||
R"#({{
|
||||
"address": "0x{:x}",
|
||||
|
@ -170,8 +171,8 @@ static std::string getWindowData(CWindow* w, HyprCtl::eHyprCtlOutputFormat forma
|
|||
"swallowing": "0x{:x}",
|
||||
"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,
|
||||
(int)w->m_vRealSize.goalv().x, (int)w->m_vRealSize.goalv().y, w->m_iWorkspaceID,
|
||||
(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.goal().x, (int)w->m_vRealSize.goal().y, w->m_iWorkspaceID,
|
||||
escapeJSONStrings(w->m_iWorkspaceID == -1 ? "" :
|
||||
g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID) ? g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID)->m_szName :
|
||||
std::string("Invalid workspace " + std::to_string(w->m_iWorkspaceID))),
|
||||
|
@ -186,8 +187,8 @@ static std::string getWindowData(CWindow* w, HyprCtl::eHyprCtlOutputFormat forma
|
|||
"{}\n\tinitialClass: {}\n\tinitialTitle: {}\n\tpid: "
|
||||
"{}\n\txwayland: {}\n\tpinned: "
|
||||
"{}\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,
|
||||
(int)w->m_vRealSize.goalv().x, (int)w->m_vRealSize.goalv().y, w->m_iWorkspaceID,
|
||||
(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.goal().y, w->m_iWorkspaceID,
|
||||
(w->m_iWorkspaceID == -1 ? "" :
|
||||
g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID) ? g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID)->m_szName :
|
||||
std::string("Invalid workspace " + std::to_string(w->m_iWorkspaceID))),
|
||||
|
@ -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 = "";
|
||||
if (format == HyprCtl::FORMAT_JSON) {
|
||||
if (format == eHyprCtlOutputFormat::FORMAT_JSON) {
|
||||
result += "[";
|
||||
|
||||
for (auto& w : g_pCompositor->m_vWindows) {
|
||||
|
@ -218,10 +219,10 @@ std::string clientsRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
|||
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 PMONITOR = g_pCompositor->getMonitorFromID(w->m_iMonitorID);
|
||||
if (format == HyprCtl::FORMAT_JSON) {
|
||||
if (format == eHyprCtlOutputFormat::FORMAT_JSON) {
|
||||
return std::format(R"#({{
|
||||
"id": {},
|
||||
"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"; };
|
||||
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 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 gapsIn = (bool)(r.gapsIn) ? std::format(",\n \"gapsIn\": {}", r.gapsIn.value()) : "";
|
||||
const std::string gapsOut = (bool)(r.gapsOut) ? std::format(",\n \"gapsOut\": {}", r.gapsOut.value()) : "";
|
||||
const std::string gapsIn = (bool)(r.gapsIn) ?
|
||||
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 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())) : "";
|
||||
|
@ -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 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 gapsIn = std::format("\tgapsIn: {}\n", (bool)(r.gapsIn) ? std::to_string(r.gapsIn.value()) : "<unset>");
|
||||
const std::string gapsOut = std::format("\tgapsOut: {}\n", (bool)(r.gapsOut) ? std::to_string(r.gapsOut.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),
|
||||
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 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>");
|
||||
|
@ -280,7 +289,7 @@ static std::string getWorkspaceRuleData(const SWorkspaceRule& r, HyprCtl::eHyprC
|
|||
return result;
|
||||
}
|
||||
}
|
||||
std::string activeWorkspaceRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||
std::string activeWorkspaceRequest(eHyprCtlOutputFormat format, std::string request) {
|
||||
if (!g_pCompositor->m_pLastMonitor)
|
||||
return "unsafe state";
|
||||
|
||||
|
@ -293,10 +302,10 @@ std::string activeWorkspaceRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
|||
return getWorkspaceData(w, format);
|
||||
}
|
||||
|
||||
std::string workspacesRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||
std::string workspacesRequest(eHyprCtlOutputFormat format, std::string request) {
|
||||
std::string result = "";
|
||||
|
||||
if (format == HyprCtl::FORMAT_JSON) {
|
||||
if (format == eHyprCtlOutputFormat::FORMAT_JSON) {
|
||||
result += "[";
|
||||
for (auto& w : g_pCompositor->m_vWorkspaces) {
|
||||
result += getWorkspaceData(w.get(), format);
|
||||
|
@ -314,9 +323,9 @@ std::string workspacesRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
|||
return result;
|
||||
}
|
||||
|
||||
std::string workspaceRulesRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||
std::string workspaceRulesRequest(eHyprCtlOutputFormat format, std::string request) {
|
||||
std::string result = "";
|
||||
if (format == HyprCtl::FORMAT_JSON) {
|
||||
if (format == eHyprCtlOutputFormat::FORMAT_JSON) {
|
||||
result += "[";
|
||||
for (auto& r : g_pConfigManager->getAllWorkspaceRules()) {
|
||||
result += getWorkspaceRuleData(r, format);
|
||||
|
@ -334,24 +343,24 @@ std::string workspaceRulesRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
|||
return result;
|
||||
}
|
||||
|
||||
std::string activeWindowRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||
std::string activeWindowRequest(eHyprCtlOutputFormat format, std::string request) {
|
||||
const auto PWINDOW = g_pCompositor->m_pLastWindow;
|
||||
|
||||
if (!g_pCompositor->windowValidMapped(PWINDOW))
|
||||
return format == HyprCtl::FORMAT_JSON ? "{}" : "Invalid";
|
||||
return format == eHyprCtlOutputFormat::FORMAT_JSON ? "{}" : "Invalid";
|
||||
|
||||
auto result = getWindowData(PWINDOW, format);
|
||||
|
||||
if (format == HyprCtl::FORMAT_JSON)
|
||||
if (format == eHyprCtlOutputFormat::FORMAT_JSON)
|
||||
result.pop_back();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string layersRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||
std::string layersRequest(eHyprCtlOutputFormat format, std::string request) {
|
||||
std::string result = "";
|
||||
|
||||
if (format == HyprCtl::FORMAT_JSON) {
|
||||
if (format == eHyprCtlOutputFormat::FORMAT_JSON) {
|
||||
result += "{\n";
|
||||
|
||||
for (auto& mon : g_pCompositor->m_vMonitors) {
|
||||
|
@ -422,9 +431,9 @@ std::string layersRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
|||
return result;
|
||||
}
|
||||
|
||||
std::string layoutsRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||
std::string layoutsRequest(eHyprCtlOutputFormat format, std::string request) {
|
||||
std::string result = "";
|
||||
if (format == HyprCtl::FORMAT_JSON) {
|
||||
if (format == eHyprCtlOutputFormat::FORMAT_JSON) {
|
||||
result += "[";
|
||||
|
||||
for (auto& m : g_pLayoutManager->getAllLayoutNames()) {
|
||||
|
@ -444,10 +453,10 @@ std::string layoutsRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
|||
return result;
|
||||
}
|
||||
|
||||
std::string devicesRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||
std::string devicesRequest(eHyprCtlOutputFormat format, std::string request) {
|
||||
std::string result = "";
|
||||
|
||||
if (format == HyprCtl::FORMAT_JSON) {
|
||||
if (format == eHyprCtlOutputFormat::FORMAT_JSON) {
|
||||
result += "{\n";
|
||||
result += "\"mice\": [\n";
|
||||
|
||||
|
@ -603,9 +612,9 @@ std::string devicesRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
|||
return result;
|
||||
}
|
||||
|
||||
std::string animationsRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||
std::string animationsRequest(eHyprCtlOutputFormat format, std::string request) {
|
||||
std::string ret = "";
|
||||
if (format == HyprCtl::eHyprCtlOutputFormat::FORMAT_NORMAL) {
|
||||
if (format == eHyprCtlOutputFormat::FORMAT_NORMAL) {
|
||||
ret += "animations:\n";
|
||||
|
||||
for (auto& ac : g_pConfigManager->getAnimationConfig()) {
|
||||
|
@ -656,10 +665,10 @@ std::string animationsRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
|||
return ret;
|
||||
}
|
||||
|
||||
std::string rollinglogRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||
std::string rollinglogRequest(eHyprCtlOutputFormat format, std::string request) {
|
||||
std::string result = "";
|
||||
|
||||
if (format == HyprCtl::FORMAT_JSON) {
|
||||
if (format == eHyprCtlOutputFormat::FORMAT_JSON) {
|
||||
result += "[\n\"log\":\"";
|
||||
result += escapeJSONStrings(Debug::rollingLog);
|
||||
result += "\"]";
|
||||
|
@ -670,10 +679,10 @@ std::string rollinglogRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
|||
return result;
|
||||
}
|
||||
|
||||
std::string globalShortcutsRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||
std::string globalShortcutsRequest(eHyprCtlOutputFormat format, std::string request) {
|
||||
std::string ret = "";
|
||||
const auto SHORTCUTS = g_pProtocolManager->m_pGlobalShortcutsProtocolManager->getAllShortcuts();
|
||||
if (format == HyprCtl::eHyprCtlOutputFormat::FORMAT_NORMAL) {
|
||||
if (format == eHyprCtlOutputFormat::FORMAT_NORMAL) {
|
||||
for (auto& sh : SHORTCUTS)
|
||||
ret += std::format("{}:{} -> {}\n", sh.appid, sh.id, sh.description);
|
||||
} else {
|
||||
|
@ -693,9 +702,9 @@ std::string globalShortcutsRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
|||
return ret;
|
||||
}
|
||||
|
||||
std::string bindsRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||
std::string bindsRequest(eHyprCtlOutputFormat format, std::string request) {
|
||||
std::string ret = "";
|
||||
if (format == HyprCtl::eHyprCtlOutputFormat::FORMAT_NORMAL) {
|
||||
if (format == eHyprCtlOutputFormat::FORMAT_NORMAL) {
|
||||
for (auto& kb : g_pKeybindManager->m_lKeybinds) {
|
||||
ret += "bind";
|
||||
if (kb.locked)
|
||||
|
@ -741,12 +750,12 @@ std::string bindsRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
|||
return ret;
|
||||
}
|
||||
|
||||
std::string versionRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||
std::string versionRequest(eHyprCtlOutputFormat format, std::string request) {
|
||||
|
||||
auto commitMsg = removeBeginEndSpacesTabs(GIT_COMMIT_MESSAGE);
|
||||
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 +
|
||||
").\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
|
||||
}
|
||||
|
||||
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
|
||||
in = in.substr(in.find_first_of(' ') + 1);
|
||||
|
||||
|
@ -814,7 +856,7 @@ std::string dispatchRequest(std::string in) {
|
|||
return "ok";
|
||||
}
|
||||
|
||||
std::string dispatchKeyword(std::string in) {
|
||||
std::string dispatchKeyword(eHyprCtlOutputFormat format, std::string in) {
|
||||
// get rid of the keyword keyword
|
||||
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);
|
||||
|
||||
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
|
||||
|
||||
if (COMMAND.contains("input") || COMMAND.contains("device:")) {
|
||||
if (COMMAND.contains("input") || COMMAND.contains("device") || COMMAND == "source") {
|
||||
g_pInputManager->setKeyboardLayout(); // update kb layout
|
||||
g_pInputManager->setPointerConfigs(); // update mouse cfgs
|
||||
g_pInputManager->setTouchDeviceConfigs(); // update touch device cfgs
|
||||
g_pInputManager->setTabletConfigs(); // update tablets
|
||||
}
|
||||
|
||||
if (COMMAND.contains("general:layout"))
|
||||
g_pLayoutManager->switchToLayout(g_pConfigManager->getString("general:layout")); // update layout
|
||||
static auto* const PLAYOUT = (Hyprlang::STRING const*)g_pConfigManager->getConfigValuePtr("general: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;
|
||||
|
||||
if (COMMAND.contains("blur")) {
|
||||
if (COMMAND.contains("blur") || COMMAND == "source") {
|
||||
for (auto& [m, rd] : g_pHyprOpenGL->m_mMonitorRenderResources) {
|
||||
rd.blurFBDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
// 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) {
|
||||
g_pHyprRenderer->damageMonitor(m.get());
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m->ID);
|
||||
|
@ -862,7 +907,7 @@ std::string dispatchKeyword(std::string in) {
|
|||
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);
|
||||
|
||||
|
@ -877,20 +922,20 @@ std::string reloadRequest(const std::string& request) {
|
|||
return "ok";
|
||||
}
|
||||
|
||||
std::string killRequest() {
|
||||
std::string killRequest(eHyprCtlOutputFormat format, std::string request) {
|
||||
g_pInputManager->setClickMode(CLICKMODE_KILL);
|
||||
|
||||
return "ok";
|
||||
}
|
||||
|
||||
std::string splashRequest() {
|
||||
std::string splashRequest(eHyprCtlOutputFormat format, std::string request) {
|
||||
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();
|
||||
|
||||
if (format == HyprCtl::FORMAT_NORMAL) {
|
||||
if (format == eHyprCtlOutputFormat::FORMAT_NORMAL) {
|
||||
return std::format("{}, {}", (int)CURSORPOS.x, (int)CURSORPOS.y);
|
||||
} else {
|
||||
return std::format(R"#(
|
||||
|
@ -905,9 +950,7 @@ std::string cursorPosRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
|||
return "error";
|
||||
}
|
||||
|
||||
std::string getReply(std::string);
|
||||
|
||||
std::string dispatchBatch(std::string request) {
|
||||
std::string dispatchBatch(eHyprCtlOutputFormat format, std::string request) {
|
||||
// split by ;
|
||||
|
||||
request = request.substr(9);
|
||||
|
@ -930,8 +973,8 @@ std::string dispatchBatch(std::string request) {
|
|||
|
||||
nextItem();
|
||||
|
||||
while (curitem != "") {
|
||||
reply += getReply(curitem);
|
||||
while (curitem != "" || request != "") {
|
||||
reply += g_pHyprCtl->getReply(curitem);
|
||||
|
||||
nextItem();
|
||||
}
|
||||
|
@ -939,7 +982,7 @@ std::string dispatchBatch(std::string request) {
|
|||
return reply;
|
||||
}
|
||||
|
||||
std::string dispatchSetCursor(std::string request) {
|
||||
std::string dispatchSetCursor(eHyprCtlOutputFormat format, std::string request) {
|
||||
CVarList vars(request, 0, ' ');
|
||||
|
||||
const auto SIZESTR = vars[vars.size() - 1];
|
||||
|
@ -971,7 +1014,7 @@ std::string dispatchSetCursor(std::string request) {
|
|||
return "ok";
|
||||
}
|
||||
|
||||
std::string switchXKBLayoutRequest(const std::string& request) {
|
||||
std::string switchXKBLayoutRequest(eHyprCtlOutputFormat format, std::string request) {
|
||||
CVarList vars(request, 0, ' ');
|
||||
|
||||
const auto KB = vars[1];
|
||||
|
@ -1017,7 +1060,7 @@ std::string switchXKBLayoutRequest(const std::string& request) {
|
|||
return "ok";
|
||||
}
|
||||
|
||||
std::string dispatchSeterror(std::string request) {
|
||||
std::string dispatchSeterror(eHyprCtlOutputFormat format, std::string request) {
|
||||
CVarList vars(request, 0, ' ');
|
||||
|
||||
std::string errorMessage = "";
|
||||
|
@ -1046,12 +1089,13 @@ std::string dispatchSeterror(std::string request) {
|
|||
return "ok";
|
||||
}
|
||||
|
||||
std::string dispatchSetProp(std::string request) {
|
||||
std::string dispatchSetProp(eHyprCtlOutputFormat format, std::string request) {
|
||||
CVarList vars(request, 0, ' ');
|
||||
|
||||
if (vars.size() < 4)
|
||||
return "not enough args";
|
||||
|
||||
const auto PLASTWINDOW = g_pCompositor->m_pLastWindow;
|
||||
const auto PWINDOW = g_pCompositor->getWindowByRegex(vars[1]);
|
||||
|
||||
if (!PWINDOW)
|
||||
|
@ -1060,6 +1104,8 @@ std::string dispatchSetProp(std::string request) {
|
|||
const auto PROP = vars[2];
|
||||
const auto VAL = vars[3];
|
||||
|
||||
auto noFocus = PWINDOW->m_sAdditionalConfigData.noFocus;
|
||||
|
||||
bool lock = false;
|
||||
|
||||
if (vars.size() > 4) {
|
||||
|
@ -1089,6 +1135,8 @@ std::string dispatchSetProp(std::string request) {
|
|||
PWINDOW->m_sAdditionalConfigData.forceNoShadow.forceSetIgnoreLocked(configStringToInt(VAL), lock);
|
||||
} else if (PROP == "forcenodim") {
|
||||
PWINDOW->m_sAdditionalConfigData.forceNoDim.forceSetIgnoreLocked(configStringToInt(VAL), lock);
|
||||
} else if (PROP == "nofocus") {
|
||||
PWINDOW->m_sAdditionalConfigData.noFocus.forceSetIgnoreLocked(configStringToInt(VAL), lock);
|
||||
} else if (PROP == "windowdancecompat") {
|
||||
PWINDOW->m_sAdditionalConfigData.windowDanceCompat.forceSetIgnoreLocked(configStringToInt(VAL), lock);
|
||||
} else if (PROP == "nomaxsize") {
|
||||
|
@ -1124,13 +1172,19 @@ std::string dispatchSetProp(std::string request) {
|
|||
|
||||
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)
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m->ID);
|
||||
|
||||
return "ok";
|
||||
}
|
||||
|
||||
std::string dispatchGetOption(std::string request, HyprCtl::eHyprCtlOutputFormat format) {
|
||||
std::string dispatchGetOption(eHyprCtlOutputFormat format, std::string request) {
|
||||
std::string curitem = "";
|
||||
|
||||
auto nextItem = [&]() {
|
||||
|
@ -1150,31 +1204,43 @@ std::string dispatchGetOption(std::string request, HyprCtl::eHyprCtlOutputFormat
|
|||
nextItem();
|
||||
nextItem();
|
||||
|
||||
const auto PCFGOPT = g_pConfigManager->getConfigValuePtrSafe(curitem);
|
||||
const auto VAR = g_pConfigManager->getHyprlangConfigValuePtr(curitem);
|
||||
|
||||
if (!PCFGOPT)
|
||||
if (!VAR)
|
||||
return "no such option";
|
||||
|
||||
if (format == HyprCtl::eHyprCtlOutputFormat::FORMAT_NORMAL)
|
||||
return std::format("option {}\n\tint: {}\n\tfloat: {:.5f}\n\tstr: \"{}\"\n\tdata: {:x}\n\tset: {}", curitem, PCFGOPT->intValue, PCFGOPT->floatValue, PCFGOPT->strValue,
|
||||
(uintptr_t)PCFGOPT->data.get(), PCFGOPT->set);
|
||||
else {
|
||||
return std::format(
|
||||
R"#(
|
||||
{{
|
||||
"option": "{}",
|
||||
"int": {},
|
||||
"float": {:.5f},
|
||||
"str": "{}",
|
||||
"data": "0x{:x}",
|
||||
"set": {}
|
||||
}}
|
||||
)#",
|
||||
curitem, PCFGOPT->intValue, PCFGOPT->floatValue, PCFGOPT->strValue, (uintptr_t)PCFGOPT->data.get(), PCFGOPT->set);
|
||||
}
|
||||
const auto VAL = VAR->getValue();
|
||||
const auto TYPE = std::type_index(VAL.type());
|
||||
|
||||
if (format == FORMAT_NORMAL) {
|
||||
if (TYPE == typeid(Hyprlang::INT))
|
||||
return std::format("int: {}\nset: {}", std::any_cast<Hyprlang::INT>(VAL), VAR->m_bSetByUser);
|
||||
else if (TYPE == typeid(Hyprlang::FLOAT))
|
||||
return std::format("float: {:2f}\nset: {}", std::any_cast<Hyprlang::FLOAT>(VAL), VAR->m_bSetByUser);
|
||||
else if (TYPE == typeid(Hyprlang::VEC2))
|
||||
return std::format("vec2: [{}, {}]\nset: {}", 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("str: {}\nset: {}", std::any_cast<Hyprlang::STRING>(VAL), VAR->m_bSetByUser);
|
||||
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 {
|
||||
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);
|
||||
}
|
||||
|
||||
std::string decorationRequest(std::string request, HyprCtl::eHyprCtlOutputFormat format) {
|
||||
return "invalid type (internal error)";
|
||||
}
|
||||
|
||||
std::string decorationRequest(eHyprCtlOutputFormat format, std::string request) {
|
||||
CVarList vars(request, 0, ' ');
|
||||
const auto PWINDOW = g_pCompositor->getWindowByRegex(vars[1]);
|
||||
|
||||
|
@ -1182,7 +1248,7 @@ std::string decorationRequest(std::string request, HyprCtl::eHyprCtlOutputFormat
|
|||
return "none";
|
||||
|
||||
std::string result = "";
|
||||
if (format == HyprCtl::FORMAT_JSON) {
|
||||
if (format == eHyprCtlOutputFormat::FORMAT_JSON) {
|
||||
result += "[";
|
||||
for (auto& wd : PWINDOW->m_dWindowDecorations) {
|
||||
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 = "";
|
||||
|
||||
auto nextItem = [&]() {
|
||||
|
@ -1280,7 +1346,7 @@ std::string dispatchOutput(std::string request) {
|
|||
return "ok";
|
||||
}
|
||||
|
||||
std::string dispatchPlugin(std::string request) {
|
||||
std::string dispatchPlugin(eHyprCtlOutputFormat format, std::string request) {
|
||||
CVarList vars(request, 0, ' ');
|
||||
|
||||
if (vars.size() < 2)
|
||||
|
@ -1323,7 +1389,7 @@ std::string dispatchPlugin(std::string request) {
|
|||
return "ok";
|
||||
}
|
||||
|
||||
std::string dispatchNotify(std::string request) {
|
||||
std::string dispatchNotify(eHyprCtlOutputFormat format, std::string request) {
|
||||
CVarList vars(request, 0, ' ');
|
||||
|
||||
if (vars.size() < 5)
|
||||
|
@ -1364,92 +1430,137 @@ std::string dispatchNotify(std::string request) {
|
|||
return "ok";
|
||||
}
|
||||
|
||||
std::string getReply(std::string request) {
|
||||
auto format = HyprCtl::FORMAT_NORMAL;
|
||||
CHyprCtl::CHyprCtl() {
|
||||
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
|
||||
if (!request.contains("[[BATCH]]") && request.contains("/")) {
|
||||
if (!request.starts_with("[[BATCH]]") && request.contains("/")) {
|
||||
long unsigned int sepIndex = 0;
|
||||
for (const auto& c : request) {
|
||||
if (c == '/') { // stop at separator
|
||||
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++;
|
||||
|
||||
if (c == 'j')
|
||||
format = HyprCtl::FORMAT_JSON;
|
||||
format = eHyprCtlOutputFormat::FORMAT_JSON;
|
||||
if (c == 'r')
|
||||
reloadAll = true;
|
||||
}
|
||||
|
||||
if (sepIndex < request.size())
|
||||
request = request.substr(sepIndex + 1); // remove flags and separator so we can compare the rest of the string
|
||||
}
|
||||
|
||||
if (request.starts_with("monitors"))
|
||||
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);
|
||||
std::string result = "";
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
std::string HyprCtl::makeDynamicCall(const std::string& input) {
|
||||
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 CHyprCtl::makeDynamicCall(const std::string& input) {
|
||||
return getReply(input);
|
||||
}
|
||||
|
||||
|
@ -1460,7 +1571,7 @@ int hyprCtlFDTick(int fd, uint32_t mask, void* data) {
|
|||
sockaddr_in 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;
|
||||
|
||||
|
@ -1490,7 +1601,7 @@ int hyprCtlFDTick(int fd, uint32_t mask, void* data) {
|
|||
std::string reply = "";
|
||||
|
||||
try {
|
||||
reply = getReply(request);
|
||||
reply = g_pHyprCtl->getReply(request);
|
||||
} catch (std::exception& e) {
|
||||
Debug::log(ERR, "Error in request: {}", e.what());
|
||||
reply = "Err: " + std::string(e.what());
|
||||
|
@ -1500,18 +1611,17 @@ int hyprCtlFDTick(int fd, uint32_t mask, void* data) {
|
|||
|
||||
close(ACCEPTEDCONNECTION);
|
||||
|
||||
if (g_pConfigManager->m_bWantsMonitorReload) {
|
||||
if (g_pConfigManager->m_bWantsMonitorReload)
|
||||
g_pConfigManager->ensureMonitorStatus();
|
||||
}
|
||||
|
||||
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.");
|
||||
return;
|
||||
}
|
||||
|
@ -1522,15 +1632,15 @@ void HyprCtl::startHyprCtlSocket() {
|
|||
|
||||
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.");
|
||||
return;
|
||||
}
|
||||
|
||||
// 10 max queued.
|
||||
listen(iSocketFD, 10);
|
||||
listen(m_iSocketFD, 10);
|
||||
|
||||
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 <fstream>
|
||||
#include "../helpers/MiscFunctions.hpp"
|
||||
#include <functional>
|
||||
|
||||
class CHyprCtl {
|
||||
public:
|
||||
CHyprCtl();
|
||||
|
||||
namespace HyprCtl {
|
||||
void startHyprCtlSocket();
|
||||
std::string makeDynamicCall(const std::string& input);
|
||||
std::shared_ptr<SHyprCtlCommand> registerCommand(SHyprCtlCommand cmd);
|
||||
void unregisterCommand(const std::shared_ptr<SHyprCtlCommand>& cmd);
|
||||
std::string getReply(std::string);
|
||||
|
||||
// very simple thread-safe request method
|
||||
inline bool requestMade = false;
|
||||
inline bool requestReady = false;
|
||||
inline std::string request = "";
|
||||
int m_iSocketFD = -1;
|
||||
|
||||
inline std::ifstream requestStream;
|
||||
private:
|
||||
void startHyprCtlSocket();
|
||||
|
||||
inline wl_event_source* hyprCtlTickSource = nullptr;
|
||||
|
||||
inline int iSocketFD = -1;
|
||||
|
||||
enum eHyprCtlOutputFormat {
|
||||
FORMAT_NORMAL = 0,
|
||||
FORMAT_JSON
|
||||
};
|
||||
std::vector<std::shared_ptr<SHyprCtlCommand>> m_vCommands;
|
||||
};
|
||||
|
||||
inline std::unique_ptr<CHyprCtl> g_pHyprCtl;
|
|
@ -227,3 +227,7 @@ void CHyprNotificationOverlay::draw(CMonitor* pMonitor) {
|
|||
CBox pMonBox = {0, 0, pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y};
|
||||
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 addNotification(const std::string& text, const CColor& color, const float timeMs, const eIcons icon = ICON_NONE);
|
||||
bool hasAny();
|
||||
|
||||
private:
|
||||
CBox drawNotifications(CMonitor* pMonitor);
|
||||
|
|
|
@ -22,7 +22,7 @@ void Debug::wlrLog(wlr_log_importance level, const char* fmt, va_list args) {
|
|||
|
||||
rollingLog += output + "\n";
|
||||
|
||||
if (!disableLogs || !*disableLogs) {
|
||||
if (!disableLogs || !**disableLogs) {
|
||||
std::ofstream ofs;
|
||||
ofs.open(logFile, std::ios::out | std::ios::app);
|
||||
ofs << "[wlr] " << output << "\n";
|
||||
|
|
|
@ -22,8 +22,8 @@ enum LogLevel {
|
|||
|
||||
namespace Debug {
|
||||
inline std::string logFile;
|
||||
inline int64_t* disableLogs = nullptr;
|
||||
inline int64_t* disableTime = nullptr;
|
||||
inline int64_t* const* disableLogs = nullptr;
|
||||
inline int64_t* const* disableTime = nullptr;
|
||||
inline bool disableStdout = false;
|
||||
inline bool trace = false;
|
||||
inline bool shuttingDown = false;
|
||||
|
@ -52,7 +52,7 @@ namespace Debug {
|
|||
}
|
||||
|
||||
// print date and time to the ofs
|
||||
if (disableTime && !*disableTime) {
|
||||
if (disableTime && !**disableTime) {
|
||||
#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())});
|
||||
#else
|
||||
|
@ -73,7 +73,7 @@ namespace Debug {
|
|||
if (rollingLog.size() > ROLLING_LOG_SIZE)
|
||||
rollingLog = rollingLog.substr(rollingLog.size() - ROLLING_LOG_SIZE);
|
||||
|
||||
if (!disableLogs || !*disableLogs) {
|
||||
if (!disableLogs || !**disableLogs) {
|
||||
// log to a file
|
||||
std::ofstream ofs;
|
||||
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
|
||||
|
||||
#include "../defines.hpp"
|
||||
#include "../helpers/Region.hpp"
|
||||
|
||||
class CWindow;
|
||||
struct SLayerSurface;
|
||||
class CSubsurface;
|
||||
class CPopup;
|
||||
|
||||
class CWLSurface {
|
||||
public:
|
||||
CWLSurface() = default;
|
||||
CWLSurface(wlr_surface* pSurface);
|
||||
~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, 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();
|
||||
|
||||
CWLSurface(const CWLSurface&) = delete;
|
||||
|
@ -23,13 +31,26 @@ class CWLSurface {
|
|||
bool small() const; // means surface is smaller than the requested size
|
||||
Vector2D correctSmallVec() const; // returns a corrective vector for small() surfaces
|
||||
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.
|
||||
bool m_bFillIgnoreSmall = false;
|
||||
|
||||
// if present, means this is a base surface of a window. Cleaned on unassign()
|
||||
CWindow* m_pOwner = nullptr;
|
||||
// track surface data and avoid dupes
|
||||
float m_fLastScale = 0;
|
||||
int m_iLastScale = 0;
|
||||
wl_output_transform m_eLastTransform = (wl_output_transform)-1;
|
||||
|
||||
//
|
||||
CWLSurface& operator=(wlr_surface* pSurface) {
|
||||
destroy();
|
||||
m_pWLRSurface = pSurface;
|
||||
|
@ -55,10 +76,18 @@ class CWLSurface {
|
|||
}
|
||||
|
||||
private:
|
||||
bool m_bInert = true;
|
||||
|
||||
wlr_surface* m_pWLRSurface = nullptr;
|
||||
|
||||
CWindow* m_pWindowOwner = nullptr;
|
||||
SLayerSurface* m_pLayerOwner = nullptr;
|
||||
CPopup* m_pPopupOwner = nullptr;
|
||||
CSubsurface* m_pSubsurfaceOwner = nullptr;
|
||||
|
||||
void destroy();
|
||||
void init();
|
||||
bool desktopComponent();
|
||||
|
||||
DYNLISTENER(destroy);
|
||||
};
|
|
@ -14,8 +14,8 @@ CWorkspace::CWorkspace(int monitorID, std::string name, bool special) {
|
|||
m_bIsSpecialWorkspace = special;
|
||||
|
||||
m_vRenderOffset.m_pWorkspace = this;
|
||||
m_vRenderOffset.create(AVARTYPE_VECTOR, special ? g_pConfigManager->getAnimationPropertyConfig("specialWorkspace") : g_pConfigManager->getAnimationPropertyConfig("workspaces"),
|
||||
nullptr, AVARDAMAGE_ENTIRE);
|
||||
m_vRenderOffset.create(special ? g_pConfigManager->getAnimationPropertyConfig("specialWorkspace") : g_pConfigManager->getAnimationPropertyConfig("workspaces"), nullptr,
|
||||
AVARDAMAGE_ENTIRE);
|
||||
m_fAlpha.m_pWorkspace = this;
|
||||
m_fAlpha.create(AVARTYPE_FLOAT, special ? g_pConfigManager->getAnimationPropertyConfig("specialWorkspace") : g_pConfigManager->getAnimationPropertyConfig("workspaces"),
|
||||
nullptr, AVARDAMAGE_ENTIRE);
|
||||
|
@ -24,6 +24,10 @@ CWorkspace::CWorkspace(int monitorID, std::string name, bool special) {
|
|||
m_vRenderOffset.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});
|
||||
EMIT_HOOK_EVENT("createWorkspace", this);
|
||||
}
|
||||
|
@ -39,7 +43,7 @@ CWorkspace::~CWorkspace() {
|
|||
|
||||
void CWorkspace::startAnim(bool in, bool left, bool instant) {
|
||||
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")) {
|
||||
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") {
|
||||
// fallback is slide
|
||||
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.
|
||||
|
||||
|
@ -104,7 +108,7 @@ void CWorkspace::startAnim(bool in, bool left, bool instant) {
|
|||
} else {
|
||||
// fallback is slide
|
||||
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.
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include "AnimatedVariable.hpp"
|
||||
#include "../helpers/AnimatedVariable.hpp"
|
||||
#include <string>
|
||||
#include "../defines.hpp"
|
||||
|
||||
|
@ -35,8 +35,8 @@ class CWorkspace {
|
|||
wl_array m_wlrCoordinateArr;
|
||||
|
||||
// for animations
|
||||
CAnimatedVariable m_vRenderOffset;
|
||||
CAnimatedVariable m_fAlpha;
|
||||
CAnimatedVariable<Vector2D> m_vRenderOffset;
|
||||
CAnimatedVariable<float> m_fAlpha;
|
||||
bool m_bForceRendering = false;
|
||||
|
||||
// "scratchpad"
|
|
@ -22,25 +22,6 @@ namespace Events {
|
|||
DYNLISTENFUNC(unmapLayerSurface);
|
||||
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)
|
||||
LISTENER(newXDGToplevel);
|
||||
LISTENER(activateXDG);
|
||||
|
@ -174,4 +155,7 @@ namespace Events {
|
|||
|
||||
// Tearing hints
|
||||
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_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_newPopup.initCallback(&WLRLAYERSURFACE->events.new_popup, &Events::listener_newPopup, layerSurface, "layerSurface");
|
||||
|
||||
layerSurface->layerSurface = WLRLAYERSURFACE;
|
||||
layerSurface->layer = WLRLAYERSURFACE->current.layer;
|
||||
|
@ -87,7 +86,6 @@ void Events::listener_destroyLayerSurface(void* owner, void* data) {
|
|||
layersurface->hyprListener_destroyLayerSurface.removeCallback();
|
||||
layersurface->hyprListener_mapLayerSurface.removeCallback();
|
||||
layersurface->hyprListener_unmapLayerSurface.removeCallback();
|
||||
layersurface->hyprListener_newPopup.removeCallback();
|
||||
|
||||
// rearrange to fix the reserved areas
|
||||
if (PMONITOR) {
|
||||
|
@ -113,8 +111,7 @@ void Events::listener_mapLayerSurface(void* owner, void* data) {
|
|||
layersurface->keyboardExclusive = layersurface->layerSurface->current.keyboard_interactive;
|
||||
layersurface->surface = layersurface->layerSurface->surface;
|
||||
|
||||
// anim
|
||||
layersurface->alpha.setConfig(g_pConfigManager->getAnimationPropertyConfig("fadeIn"));
|
||||
layersurface->popupHead = std::make_unique<CPopup>(layersurface);
|
||||
|
||||
// fix if it changed its mon
|
||||
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);
|
||||
|
||||
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 &&
|
||||
// don't focus if constrained
|
||||
(!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 bool FULLSCREEN = WORKSPACE->m_bHasFullscreenWindow && WORKSPACE->m_efFullscreenMode == FULLSCREEN_FULL;
|
||||
|
||||
layersurface->alpha.setValue(0);
|
||||
layersurface->alpha = ((layersurface->layer == ZWLR_LAYER_SHELL_V1_LAYER_TOP && FULLSCREEN && !GRABSFOCUS) ? 0.f : 1.f);
|
||||
layersurface->startAnimation(!(layersurface->layer == ZWLR_LAYER_SHELL_V1_LAYER_TOP && FULLSCREEN && !GRABSFOCUS));
|
||||
layersurface->readyToDelete = 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 : "")});
|
||||
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) {
|
||||
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->fadingOut = true;
|
||||
|
||||
layersurface->alpha.setValueAndWarp(0.f);
|
||||
layersurface->startAnimation(false);
|
||||
return;
|
||||
}
|
||||
|
||||
// anim
|
||||
layersurface->alpha.setConfig(g_pConfigManager->getAnimationPropertyConfig("fadeOut"));
|
||||
|
||||
// make a snapshot and start fade
|
||||
g_pHyprOpenGL->makeLayerSnapshot(layersurface);
|
||||
layersurface->alpha = 0.f;
|
||||
|
||||
layersurface->startAnimation(false);
|
||||
|
||||
layersurface->mapped = false;
|
||||
|
||||
layersurface->fadingOut = true;
|
||||
|
||||
g_pCompositor->addToFadingOutSafe(layersurface);
|
||||
|
||||
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 &&
|
||||
(!g_pCompositor->m_sSeat.mouse || !g_pCompositor->m_sSeat.mouse->currentConstraint) // don't focus if constrained
|
||||
&& !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.dragIcon = nullptr;
|
||||
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) {
|
||||
|
@ -176,10 +178,16 @@ void Events::listener_powerMgrSetMode(wl_listener* listener, void* data) {
|
|||
Debug::log(LOG, "PowerMgr set mode!");
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
|
@ -225,16 +233,7 @@ void Events::listener_setCursorShape(wl_listener* listener, void* data) {
|
|||
}
|
||||
|
||||
void Events::listener_newTearingHint(wl_listener* listener, void* data) {
|
||||
const auto TCTL = (wlr_tearing_control_v1*)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);
|
||||
Debug::log(LOG, "New tearing hint at {:x}", (uintptr_t)data);
|
||||
|
||||
const auto NEWCTRL = g_pHyprRenderer->m_vTearingControllers.emplace_back(std::make_unique<STearingController>()).get();
|
||||
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->pWlrHint->events.destroy,
|
||||
[&](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; });
|
||||
},
|
||||
|
@ -256,10 +255,27 @@ void Events::listener_newTearingHint(wl_listener* listener, void* data) {
|
|||
const auto PWINDOW = g_pCompositor->getWindowFromSurface(TEARINGHINT->pWlrHint->surface);
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
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) {
|
||||
if (w->m_iMonitorID == PNEWMONITOR->ID) {
|
||||
w->m_iLastSurfaceMonitorID = -1;
|
||||
w->updateSurfaceOutputs();
|
||||
w->updateSurfaceScaleTransformDetails();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -147,12 +147,12 @@ void Events::listener_monitorFrame(void* owner, void* data) {
|
|||
PMONITOR->tearingState.frameScheduledWhileBusy = false;
|
||||
}
|
||||
|
||||
static auto* const PENABLERAT = &g_pConfigManager->getConfigValuePtr("misc:render_ahead_of_time")->intValue;
|
||||
static auto* const PRATSAFE = &g_pConfigManager->getConfigValuePtr("misc:render_ahead_safezone")->intValue;
|
||||
static auto* const PENABLERAT = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("misc:render_ahead_of_time");
|
||||
static auto* const PRATSAFE = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("misc:render_ahead_safezone");
|
||||
|
||||
PMONITOR->lastPresentationTimer.reset();
|
||||
|
||||
if (*PENABLERAT && !PMONITOR->tearingState.nextRenderTorn) {
|
||||
if (**PENABLERAT && !PMONITOR->tearingState.nextRenderTorn) {
|
||||
if (!PMONITOR->RATScheduled) {
|
||||
// render
|
||||
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);
|
||||
|
||||
if (max + *PRATSAFE > 1000.0 / PMONITOR->refreshRate)
|
||||
if (max + **PRATSAFE > 1000.0 / PMONITOR->refreshRate)
|
||||
return;
|
||||
|
||||
const auto MSLEFT = 1000.0 / PMONITOR->refreshRate - PMONITOR->lastPresentationTimer.getMillis();
|
||||
|
||||
PMONITOR->RATScheduled = true;
|
||||
|
||||
const auto ESTRENDERTIME = std::ceil(avg + *PRATSAFE);
|
||||
const auto ESTRENDERTIME = std::ceil(avg + **PRATSAFE);
|
||||
const auto TIMETOSLEEP = std::floor(MSLEFT - ESTRENDERTIME);
|
||||
|
||||
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 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) {
|
||||
|
|
|
@ -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) {
|
||||
const auto PWINDOW = (CWindow*)pWindow;
|
||||
*x += PWINDOW->m_vRealPosition.goalv().x;
|
||||
*y += PWINDOW->m_vRealPosition.goalv().y;
|
||||
*x += PWINDOW->m_vRealPosition.goal().x;
|
||||
*y += PWINDOW->m_vRealPosition.goal().y;
|
||||
|
||||
if (!PWINDOW->m_bIsX11 && PWINDOW->m_bIsMapped) {
|
||||
wlr_box geom;
|
||||
|
@ -32,7 +32,7 @@ void addViewCoords(void* pWindow, int* x, int* y) {
|
|||
void setAnimToMove(void* data) {
|
||||
auto* const PANIMCFG = g_pConfigManager->getAnimationPropertyConfig("windowsMove");
|
||||
|
||||
CAnimatedVariable* animvar = (CAnimatedVariable*)data;
|
||||
CBaseAnimatedVariable* animvar = (CBaseAnimatedVariable*)data;
|
||||
|
||||
animvar->setConfig(PANIMCFG);
|
||||
}
|
||||
|
@ -40,17 +40,16 @@ void setAnimToMove(void* data) {
|
|||
void Events::listener_mapWindow(void* owner, void* data) {
|
||||
CWindow* PWINDOW = (CWindow*)owner;
|
||||
|
||||
static auto* const PINACTIVEALPHA = &g_pConfigManager->getConfigValuePtr("decoration:inactive_opacity")->floatValue;
|
||||
static auto* const PACTIVEALPHA = &g_pConfigManager->getConfigValuePtr("decoration:active_opacity")->floatValue;
|
||||
static auto* const PDIMSTRENGTH = &g_pConfigManager->getConfigValuePtr("decoration:dim_strength")->floatValue;
|
||||
static auto* const PSWALLOW = &g_pConfigManager->getConfigValuePtr("misc:enable_swallow")->intValue;
|
||||
static auto* const PSWALLOWREGEX = &g_pConfigManager->getConfigValuePtr("misc:swallow_regex")->strValue;
|
||||
static auto* const PSWALLOWEXREGEX = &g_pConfigManager->getConfigValuePtr("misc:swallow_exception_regex")->strValue;
|
||||
static auto* const PNEWTAKESOVERFS = &g_pConfigManager->getConfigValuePtr("misc:new_window_takes_over_fullscreen")->intValue;
|
||||
static auto* const PINACTIVEALPHA = (Hyprlang::FLOAT* const*)g_pConfigManager->getConfigValuePtr("decoration:inactive_opacity");
|
||||
static auto* const PACTIVEALPHA = (Hyprlang::FLOAT* const*)g_pConfigManager->getConfigValuePtr("decoration:active_opacity");
|
||||
static auto* const PDIMSTRENGTH = (Hyprlang::FLOAT* const*)g_pConfigManager->getConfigValuePtr("decoration:dim_strength");
|
||||
static auto* const PSWALLOW = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("misc:enable_swallow");
|
||||
static auto* const PSWALLOWREGEX = (Hyprlang::STRING const*)g_pConfigManager->getConfigValuePtr("misc:swallow_regex");
|
||||
static auto* const PSWALLOWEXREGEX = (Hyprlang::STRING const*)g_pConfigManager->getConfigValuePtr("misc:swallow_exception_regex");
|
||||
static auto* const PNEWTAKESOVERFS = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("misc:new_window_takes_over_fullscreen");
|
||||
|
||||
auto PMONITOR = g_pCompositor->m_pLastMonitor;
|
||||
const auto PWORKSPACE =
|
||||
PMONITOR->specialWorkspaceID ? g_pCompositor->getWorkspaceByID(PMONITOR->specialWorkspaceID) : g_pCompositor->getWorkspaceByID(PMONITOR->activeWorkspace);
|
||||
auto PWORKSPACE = PMONITOR->specialWorkspaceID ? g_pCompositor->getWorkspaceByID(PMONITOR->specialWorkspaceID) : g_pCompositor->getWorkspaceByID(PMONITOR->activeWorkspace);
|
||||
PWINDOW->m_iMonitorID = PMONITOR->ID;
|
||||
PWINDOW->m_iWorkspaceID = PMONITOR->specialWorkspaceID ? PMONITOR->specialWorkspaceID : PMONITOR->activeWorkspace;
|
||||
PWINDOW->m_bIsMapped = true;
|
||||
|
@ -101,7 +100,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
|||
}
|
||||
|
||||
// window rules
|
||||
const auto WINDOWRULES = g_pConfigManager->getMatchingRules(PWINDOW);
|
||||
const auto WINDOWRULES = g_pConfigManager->getMatchingRules(PWINDOW, false);
|
||||
std::string requestedWorkspace = "";
|
||||
bool workspaceSilent = false;
|
||||
bool requestsFullscreen = PWINDOW->m_bWantsInitialFullscreen ||
|
||||
|
@ -173,13 +172,23 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
|||
} else if (r.szRule.starts_with("pseudo")) {
|
||||
PWINDOW->m_bIsPseudotiled = true;
|
||||
} else if (r.szRule.starts_with("nofocus")) {
|
||||
PWINDOW->m_bNoFocus = true;
|
||||
PWINDOW->m_sAdditionalConfigData.noFocus = true;
|
||||
} else if (r.szRule.starts_with("noinitialfocus")) {
|
||||
PWINDOW->m_bNoInitialFocus = true;
|
||||
} else if (r.szRule.starts_with("nofullscreenrequest")) {
|
||||
PWINDOW->m_bNoFullscreenRequest = true;
|
||||
} else if (r.szRule.starts_with("nomaximizerequest")) {
|
||||
PWINDOW->m_bNoMaximizeRequest = true;
|
||||
} else if (r.szRule.starts_with("suppressevent")) {
|
||||
CVarList vars(r.szRule, 0, 's', true);
|
||||
for (size_t i = 1; i < vars.size(); ++i) {
|
||||
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") {
|
||||
requestsFullscreen = true;
|
||||
overridingNoFullscreen = true;
|
||||
|
@ -270,6 +279,8 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
|||
if (!pWorkspace)
|
||||
pWorkspace = g_pCompositor->createNewWorkspace(REQUESTEDWORKSPACEID, PWINDOW->m_iMonitorID, requestedWorkspaceName);
|
||||
|
||||
PWORKSPACE = pWorkspace;
|
||||
|
||||
PWINDOW->m_iWorkspaceID = pWorkspace->m_iID;
|
||||
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);
|
||||
|
||||
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);
|
||||
} 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 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;
|
||||
g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goalv());
|
||||
g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goal());
|
||||
|
||||
PWINDOW->setHidden(false);
|
||||
} 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 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;
|
||||
g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goalv());
|
||||
g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goal());
|
||||
|
||||
PWINDOW->setHidden(false);
|
||||
} 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;
|
||||
} else {
|
||||
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;
|
||||
} else {
|
||||
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();
|
||||
|
||||
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),
|
||||
(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);
|
||||
|
@ -424,26 +435,26 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
|||
if (ARGS[1] == "1")
|
||||
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
|
||||
// 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);
|
||||
} else {
|
||||
g_pLayoutManager->getCurrentLayout()->onWindowCreated(PWINDOW);
|
||||
|
||||
// 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;
|
||||
|
||||
if (PWINDOW->m_sAdditionalConfigData.forceAllowsInput) {
|
||||
PWINDOW->m_bNoFocus = false;
|
||||
PWINDOW->m_sAdditionalConfigData.noFocus = false;
|
||||
PWINDOW->m_bNoInitialFocus = false;
|
||||
PWINDOW->m_bX11ShouldntFocus = false;
|
||||
}
|
||||
|
@ -454,9 +465,9 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
|||
if (PLSFROMFOCUS && PLSFROMFOCUS->layerSurface->current.keyboard_interactive)
|
||||
PWINDOW->m_bNoInitialFocus = true;
|
||||
if (PWORKSPACE->m_bHasFullscreenWindow && !requestsFullscreen && !PWINDOW->m_bIsFloating) {
|
||||
if (*PNEWTAKESOVERFS == 0)
|
||||
if (**PNEWTAKESOVERFS == 0)
|
||||
PWINDOW->m_bNoInitialFocus = true;
|
||||
else if (*PNEWTAKESOVERFS == 2)
|
||||
else if (**PNEWTAKESOVERFS == 2)
|
||||
g_pCompositor->setWindowFullscreen(g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID), false, FULLSCREEN_INVALID);
|
||||
else if (PWORKSPACE->m_efFullscreenMode == FULLSCREEN_MAXIMIZED)
|
||||
requestsMaximize = true;
|
||||
|
@ -464,22 +475,19 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
|||
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 &&
|
||||
(!PFORCEFOCUS || PFORCEFOCUS == PWINDOW)) {
|
||||
g_pCompositor->focusWindow(PWINDOW);
|
||||
PWINDOW->m_fActiveInactiveAlpha.setValueAndWarp(*PACTIVEALPHA);
|
||||
PWINDOW->m_fDimPercent.setValueAndWarp(PWINDOW->m_sAdditionalConfigData.forceNoDim ? 0.f : *PDIMSTRENGTH);
|
||||
PWINDOW->m_fActiveInactiveAlpha.setValueAndWarp(**PACTIVEALPHA);
|
||||
PWINDOW->m_fDimPercent.setValueAndWarp(PWINDOW->m_sAdditionalConfigData.forceNoDim ? 0.f : **PDIMSTRENGTH);
|
||||
} else {
|
||||
PWINDOW->m_fActiveInactiveAlpha.setValueAndWarp(*PINACTIVEALPHA);
|
||||
PWINDOW->m_fActiveInactiveAlpha.setValueAndWarp(**PINACTIVEALPHA);
|
||||
PWINDOW->m_fDimPercent.setValueAndWarp(0);
|
||||
}
|
||||
|
||||
Debug::log(LOG, "Window got assigned a surfaceTreeNode {:x}", (uintptr_t)PWINDOW->m_pSurfaceTree);
|
||||
|
||||
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_newPopupXDG.initCallback(&PWINDOW->m_uSurface.xdg->events.new_popup, &Events::listener_newPopupXDG, PWINDOW, "XDG Window Late");
|
||||
PWINDOW->hyprListener_requestMaximize.initCallback(&PWINDOW->m_uSurface.xdg->toplevel->events.request_maximize, &Events::listener_requestMaximize, PWINDOW,
|
||||
"XDG Window Late");
|
||||
PWINDOW->hyprListener_requestMinimize.initCallback(&PWINDOW->m_uSurface.xdg->toplevel->events.request_minimize, &Events::listener_requestMinimize, PWINDOW,
|
||||
|
@ -504,8 +512,8 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
|||
"XWayland Window Late");
|
||||
}
|
||||
|
||||
if ((requestsFullscreen && (!PWINDOW->m_bNoFullscreenRequest || overridingNoFullscreen)) || (requestsMaximize && (!PWINDOW->m_bNoMaximizeRequest || overridingNoMaximize)) ||
|
||||
requestsFakeFullscreen) {
|
||||
if ((requestsFullscreen && (!(PWINDOW->m_eSuppressedEvents & SUPPRESS_FULLSCREEN) || overridingNoFullscreen)) ||
|
||||
(requestsMaximize && (!(PWINDOW->m_eSuppressedEvents & SUPPRESS_MAXIMIZE) || overridingNoMaximize)) || requestsFakeFullscreen) {
|
||||
// fix fullscreen on requested (basically do a switcheroo)
|
||||
if (PWORKSPACE->m_bHasFullscreenWindow) {
|
||||
const auto PFULLWINDOW = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID);
|
||||
|
@ -527,8 +535,6 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
|||
// recheck idle inhibitors
|
||||
g_pInputManager->recheckIdleInhibitorStatus();
|
||||
|
||||
PWINDOW->m_pSurfaceTree = SubsurfaceTree::createTreeRoot(PWINDOW->m_pWLSurface.wlr(), addViewCoords, PWINDOW, PWINDOW);
|
||||
|
||||
PWINDOW->updateToplevel();
|
||||
|
||||
if (workspaceSilent) {
|
||||
|
@ -540,7 +546,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
|||
}
|
||||
|
||||
// verify swallowing
|
||||
if (*PSWALLOW && *PSWALLOWREGEX != STRVAL_EMPTY) {
|
||||
if (**PSWALLOW && std::string{*PSWALLOWREGEX} != STRVAL_EMPTY) {
|
||||
// don't swallow ourselves
|
||||
std::regex rgx(*PSWALLOWREGEX);
|
||||
if (!std::regex_match(g_pXWaylandManager->getAppIDClass(PWINDOW), rgx)) {
|
||||
|
@ -587,7 +593,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
|||
if (finalFound) {
|
||||
bool valid = std::regex_match(g_pXWaylandManager->getAppIDClass(finalFound), rgx);
|
||||
|
||||
if (*PSWALLOWEXREGEX != STRVAL_EMPTY) {
|
||||
if (std::string{*PSWALLOWEXREGEX} != STRVAL_EMPTY) {
|
||||
std::regex exc(*PSWALLOWEXREGEX);
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
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->setPreferredTransformForSurface(PWINDOW->m_pWLSurface.wlr(), PMONITOR->transform);
|
||||
|
||||
if (!g_pCompositor->m_sSeat.mouse || !g_pCompositor->m_sSeat.mouse->constraintActive)
|
||||
g_pInputManager->sendMotionEventsToFocused();
|
||||
|
||||
// fix some xwayland apps that don't behave nicely
|
||||
PWINDOW->m_vReportedSize = PWINDOW->m_vPendingReportedSize;
|
||||
|
||||
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) {
|
||||
|
@ -660,8 +670,8 @@ void Events::listener_unmapWindow(void* owner, void* data) {
|
|||
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID);
|
||||
if (PMONITOR) {
|
||||
PWINDOW->m_vOriginalClosedPos = PWINDOW->m_vRealPosition.vec() - PMONITOR->vecPosition;
|
||||
PWINDOW->m_vOriginalClosedSize = PWINDOW->m_vRealSize.vec();
|
||||
PWINDOW->m_vOriginalClosedPos = PWINDOW->m_vRealPosition.value() - PMONITOR->vecPosition;
|
||||
PWINDOW->m_vOriginalClosedSize = PWINDOW->m_vRealSize.value();
|
||||
PWINDOW->m_eOriginalClosedExtents = PWINDOW->getFullWindowExtents();
|
||||
}
|
||||
|
||||
|
@ -673,7 +683,6 @@ void Events::listener_unmapWindow(void* owner, void* data) {
|
|||
if (!PWINDOW->m_bIsX11) {
|
||||
Debug::log(LOG, "Unregistered late callbacks XDG");
|
||||
PWINDOW->hyprListener_setTitleWindow.removeCallback();
|
||||
PWINDOW->hyprListener_newPopupXDG.removeCallback();
|
||||
PWINDOW->hyprListener_requestMaximize.removeCallback();
|
||||
PWINDOW->hyprListener_requestMinimize.removeCallback();
|
||||
PWINDOW->hyprListener_requestMove.removeCallback();
|
||||
|
@ -745,11 +754,6 @@ void Events::listener_unmapWindow(void* owner, void* data) {
|
|||
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;
|
||||
|
||||
g_pCompositor->addToFadingOutSafe(PWINDOW);
|
||||
|
@ -757,7 +761,7 @@ void Events::listener_unmapWindow(void* owner, void* data) {
|
|||
g_pHyprRenderer->damageMonitor(g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID));
|
||||
|
||||
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
|
||||
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) {
|
||||
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())
|
||||
return;
|
||||
|
||||
|
@ -803,11 +831,14 @@ void Events::listener_commitWindow(void* owner, void* data) {
|
|||
PWINDOW->m_pPendingSizeAck.reset();
|
||||
}
|
||||
|
||||
PWINDOW->updateSurfaceOutputs();
|
||||
|
||||
g_pHyprRenderer->damageSurface(PWINDOW->m_pWLSurface.wlr(), PWINDOW->m_vRealPosition.goalv().x, PWINDOW->m_vRealPosition.goalv().y,
|
||||
g_pHyprRenderer->damageSurface(PWINDOW->m_pWLSurface.wlr(), PWINDOW->m_vRealPosition.goal().x, PWINDOW->m_vRealPosition.goal().y,
|
||||
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)
|
||||
return;
|
||||
|
||||
|
@ -817,7 +848,7 @@ void Events::listener_commitWindow(void* owner, void* data) {
|
|||
if (MAXSIZE < Vector2D{1, 1})
|
||||
return;
|
||||
|
||||
const auto REALSIZE = PWINDOW->m_vRealSize.goalv();
|
||||
const auto REALSIZE = PWINDOW->m_vRealSize.goal();
|
||||
Vector2D newSize = REALSIZE;
|
||||
|
||||
if (MAXSIZE.x < newSize.x)
|
||||
|
@ -831,7 +862,7 @@ void Events::listener_commitWindow(void* owner, void* data) {
|
|||
|
||||
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;
|
||||
g_pXWaylandManager->setWindowSize(PWINDOW, newSize, true);
|
||||
g_pHyprRenderer->damageWindow(PWINDOW);
|
||||
|
@ -861,14 +892,10 @@ void Events::listener_destroyWindow(void* owner, void* data) {
|
|||
|
||||
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_uSurface.xdg = nullptr;
|
||||
|
||||
if (!PWINDOW->m_bFadingOut) {
|
||||
Debug::log(LOG, "Unmapped {} removed instantly", PWINDOW);
|
||||
g_pCompositor->removeWindowFromVectorSafe(PWINDOW); // most likely X11 unmanaged or sumn
|
||||
|
@ -906,7 +933,7 @@ void Events::listener_fullscreenWindow(void* owner, void* data) {
|
|||
return;
|
||||
}
|
||||
|
||||
if (PWINDOW->isHidden() || PWINDOW->m_bNoFullscreenRequest)
|
||||
if (PWINDOW->isHidden() || (PWINDOW->m_eSuppressedEvents & SUPPRESS_FULLSCREEN))
|
||||
return;
|
||||
|
||||
bool requestedFullState = false;
|
||||
|
@ -960,7 +987,7 @@ void Events::listener_fullscreenWindow(void* owner, void* data) {
|
|||
void Events::listener_activateXDG(wl_listener* listener, void* 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);
|
||||
|
||||
|
@ -969,7 +996,7 @@ void Events::listener_activateXDG(wl_listener* listener, void* data) {
|
|||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
if (!*PFOCUSONACTIVATE)
|
||||
if (!**PFOCUSONACTIVATE || (PWINDOW->m_eSuppressedEvents & SUPPRESS_ACTIVATE_FOCUSONLY))
|
||||
return;
|
||||
|
||||
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) {
|
||||
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);
|
||||
|
||||
|
@ -1001,17 +1028,20 @@ void Events::listener_activateX11(void* owner, void* data) {
|
|||
if (g_pCompositor->m_pLastWindow && g_pCompositor->m_pLastWindow->getPID() != PWINDOW->getPID())
|
||||
return;
|
||||
|
||||
if (!wlr_xwayland_or_surface_wants_focus(PWINDOW->m_uSurface.xwayland))
|
||||
return;
|
||||
|
||||
g_pCompositor->focusWindow(PWINDOW);
|
||||
return;
|
||||
}
|
||||
|
||||
if (PWINDOW == g_pCompositor->m_pLastWindow)
|
||||
if (PWINDOW == g_pCompositor->m_pLastWindow || (PWINDOW->m_eSuppressedEvents & SUPPRESS_ACTIVATE))
|
||||
return;
|
||||
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"urgent", std::format("{:x}", (uintptr_t)PWINDOW)});
|
||||
EMIT_HOOK_EVENT("urgent", PWINDOW);
|
||||
|
||||
if (!*PFOCUSONACTIVATE)
|
||||
if (!**PFOCUSONACTIVATE || (PWINDOW->m_eSuppressedEvents & SUPPRESS_ACTIVATE_FOCUSONLY))
|
||||
return;
|
||||
|
||||
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);
|
||||
PWINDOW->m_vPendingReportedSize = {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;
|
||||
}
|
||||
|
||||
g_pHyprRenderer->damageWindow(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_pHyprRenderer->damageWindow(PWINDOW);
|
||||
return;
|
||||
|
@ -1052,17 +1084,16 @@ void Events::listener_configureX11(void* owner, void* data) {
|
|||
PWINDOW->m_vRealPosition.setValueAndWarp(LOGICALPOS);
|
||||
PWINDOW->m_vRealSize.setValueAndWarp(Vector2D(E->width, E->height));
|
||||
|
||||
static auto* const PXWLFORCESCALEZERO = &g_pConfigManager->getConfigValuePtr("xwayland:force_zero_scaling")->intValue;
|
||||
if (*PXWLFORCESCALEZERO) {
|
||||
static auto* const PXWLFORCESCALEZERO = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("xwayland:force_zero_scaling");
|
||||
if (**PXWLFORCESCALEZERO) {
|
||||
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.goalv() / PMONITOR->scale);
|
||||
PWINDOW->m_vRealPosition.setValueAndWarp(PWINDOW->m_vRealPosition.goalv() + DELTA / 2.0);
|
||||
PWINDOW->m_vRealSize.setValueAndWarp(PWINDOW->m_vRealSize.goal() / PMONITOR->scale);
|
||||
PWINDOW->m_fX11SurfaceScaledBy = PMONITOR->scale;
|
||||
}
|
||||
}
|
||||
|
||||
PWINDOW->m_vPosition = PWINDOW->m_vRealPosition.vec();
|
||||
PWINDOW->m_vSize = PWINDOW->m_vRealSize.vec();
|
||||
PWINDOW->m_vPosition = PWINDOW->m_vRealPosition.value();
|
||||
PWINDOW->m_vSize = PWINDOW->m_vRealSize.value();
|
||||
|
||||
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))
|
||||
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);
|
||||
|
||||
|
@ -1092,8 +1123,8 @@ void Events::listener_unmanagedSetGeometry(void* owner, void* data) {
|
|||
if (!PWINDOW->m_bIsMapped)
|
||||
return;
|
||||
|
||||
const auto POS = PWINDOW->m_vRealPosition.goalv();
|
||||
const auto SIZ = PWINDOW->m_vRealSize.goalv();
|
||||
const auto POS = PWINDOW->m_vRealPosition.goal();
|
||||
const auto SIZ = PWINDOW->m_vRealSize.goal();
|
||||
|
||||
if (PWINDOW->m_uSurface.xwayland->width > 1 && PWINDOW->m_uSurface.xwayland->height > 1)
|
||||
PWINDOW->setHidden(false);
|
||||
|
@ -1101,12 +1132,12 @@ void Events::listener_unmanagedSetGeometry(void* owner, void* data) {
|
|||
PWINDOW->setHidden(true);
|
||||
|
||||
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);
|
||||
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});
|
||||
|
||||
|
@ -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)
|
||||
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) {
|
||||
const Vector2D DELTA = PWINDOW->m_vRealSize.goalv() - PWINDOW->m_vRealSize.goalv() / PMONITOR->scale;
|
||||
PWINDOW->m_vRealSize.setValueAndWarp(PWINDOW->m_vRealSize.goalv() / PMONITOR->scale);
|
||||
PWINDOW->m_vRealPosition.setValueAndWarp(PWINDOW->m_vRealPosition.goalv() + DELTA / 2.0);
|
||||
const Vector2D DELTA = PWINDOW->m_vRealSize.goal() - PWINDOW->m_vRealSize.goal() / PMONITOR->scale;
|
||||
PWINDOW->m_vRealSize.setValueAndWarp(PWINDOW->m_vRealSize.goal() / PMONITOR->scale);
|
||||
PWINDOW->m_vRealPosition.setValueAndWarp(PWINDOW->m_vRealPosition.goal() + DELTA / 2.0);
|
||||
}
|
||||
}
|
||||
|
||||
PWINDOW->m_vPosition = PWINDOW->m_vRealPosition.goalv();
|
||||
PWINDOW->m_vSize = PWINDOW->m_vRealSize.goalv();
|
||||
PWINDOW->m_vPosition = PWINDOW->m_vRealPosition.goal();
|
||||
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);
|
||||
PWINDOW->updateWindowDecos();
|
||||
g_pHyprRenderer->damageWindow(PWINDOW);
|
||||
|
||||
PWINDOW->m_vReportedPosition = PWINDOW->m_vRealPosition.goalv();
|
||||
PWINDOW->m_vReportedSize = PWINDOW->m_vRealSize.goalv();
|
||||
PWINDOW->m_vPendingReportedSize = PWINDOW->m_vReportedSize;
|
||||
PWINDOW->m_vReportedPosition = PWINDOW->m_vRealPosition.goal();
|
||||
PWINDOW->m_vPendingReportedSize = PWINDOW->m_vRealSize.goal();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1211,7 +1241,7 @@ void Events::listener_NewXDGDeco(wl_listener* listener, void* data) {
|
|||
void Events::listener_requestMaximize(void* owner, void* data) {
|
||||
const auto PWINDOW = (CWindow*)owner;
|
||||
|
||||
if (PWINDOW->m_bNoMaximizeRequest)
|
||||
if (PWINDOW->m_eSuppressedEvents & SUPPRESS_MAXIMIZE)
|
||||
return;
|
||||
|
||||
Debug::log(LOG, "Maximize request for {}", PWINDOW);
|
||||
|
|
|
@ -2,12 +2,11 @@
|
|||
#include "../managers/AnimationManager.hpp"
|
||||
#include "../config/ConfigManager.hpp"
|
||||
|
||||
CAnimatedVariable::CAnimatedVariable() {
|
||||
CBaseAnimatedVariable::CBaseAnimatedVariable(ANIMATEDVARTYPE type) : m_Type(type) {
|
||||
; // dummy var
|
||||
}
|
||||
|
||||
void CAnimatedVariable::create(ANIMATEDVARTYPE type, SAnimationPropertyConfig* pAnimConfig, void* pWindow, AVARDAMAGEPOLICY policy) {
|
||||
m_eVarType = type;
|
||||
void CBaseAnimatedVariable::create(SAnimationPropertyConfig* pAnimConfig, void* pWindow, AVARDAMAGEPOLICY policy) {
|
||||
m_eDamagePolicy = policy;
|
||||
m_pConfig = pAnimConfig;
|
||||
m_pWindow = pWindow;
|
||||
|
@ -15,42 +14,11 @@ void CAnimatedVariable::create(ANIMATEDVARTYPE type, SAnimationPropertyConfig* p
|
|||
m_bDummy = false;
|
||||
}
|
||||
|
||||
void CAnimatedVariable::create(ANIMATEDVARTYPE type, std::any val, SAnimationPropertyConfig* pAnimConfig, void* pWindow, AVARDAMAGEPOLICY policy) {
|
||||
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() {
|
||||
CBaseAnimatedVariable::~CBaseAnimatedVariable() {
|
||||
unregister();
|
||||
}
|
||||
|
||||
void CAnimatedVariable::unregister() {
|
||||
void CBaseAnimatedVariable::unregister() {
|
||||
if (!g_pAnimationManager)
|
||||
return;
|
||||
std::erase_if(g_pAnimationManager->m_vAnimatedVariables, [&](const auto& other) { return other == this; });
|
||||
|
@ -58,23 +26,26 @@ void CAnimatedVariable::unregister() {
|
|||
disconnectFromActive();
|
||||
}
|
||||
|
||||
void CAnimatedVariable::registerVar() {
|
||||
void CBaseAnimatedVariable::registerVar() {
|
||||
if (!m_bIsRegistered)
|
||||
g_pAnimationManager->m_vAnimatedVariables.push_back(this);
|
||||
m_bIsRegistered = true;
|
||||
}
|
||||
|
||||
int CAnimatedVariable::getDurationLeftMs() {
|
||||
int CBaseAnimatedVariable::getDurationLeftMs() {
|
||||
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);
|
||||
}
|
||||
|
||||
float CAnimatedVariable::getPercent() {
|
||||
float CBaseAnimatedVariable::getPercent() {
|
||||
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);
|
||||
}
|
||||
|
||||
float CAnimatedVariable::getCurveValue() {
|
||||
float CBaseAnimatedVariable::getCurveValue() {
|
||||
if (!m_bIsBeingAnimated)
|
||||
return 1.f;
|
||||
|
||||
const auto SPENT = getPercent();
|
||||
|
||||
if (SPENT >= 1.f)
|
||||
|
@ -83,7 +54,7 @@ float CAnimatedVariable::getCurveValue() {
|
|||
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
|
||||
|
||||
if (!m_bIsConnectedToActive)
|
||||
|
@ -92,7 +63,7 @@ void CAnimatedVariable::connectToActive() {
|
|||
m_bIsConnectedToActive = true;
|
||||
}
|
||||
|
||||
void CAnimatedVariable::disconnectFromActive() {
|
||||
void CBaseAnimatedVariable::disconnectFromActive() {
|
||||
std::erase_if(g_pAnimationManager->m_vActiveAnimatedVariables, [&](const auto& other) { return other == this; });
|
||||
m_bIsConnectedToActive = false;
|
||||
}
|
|
@ -3,6 +3,7 @@
|
|||
#include <functional>
|
||||
#include <any>
|
||||
#include <chrono>
|
||||
#include <type_traits>
|
||||
#include "Vector2D.hpp"
|
||||
#include "Color.hpp"
|
||||
#include "../macros.hpp"
|
||||
|
@ -15,6 +16,30 @@ enum ANIMATEDVARTYPE {
|
|||
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 {
|
||||
AVARDAMAGE_NONE = -1,
|
||||
AVARDAMAGE_ENTIRE = 0,
|
||||
|
@ -28,174 +53,34 @@ struct SLayerSurface;
|
|||
struct SAnimationPropertyConfig;
|
||||
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:
|
||||
CAnimatedVariable(); // dummy var
|
||||
CBaseAnimatedVariable(ANIMATEDVARTYPE type);
|
||||
void create(SAnimationPropertyConfig* pAnimConfig, void* pWindow, AVARDAMAGEPOLICY policy);
|
||||
|
||||
void create(ANIMATEDVARTYPE, SAnimationPropertyConfig*, void* pWindow, AVARDAMAGEPOLICY);
|
||||
void create(ANIMATEDVARTYPE, std::any val, SAnimationPropertyConfig*, void* pWindow, AVARDAMAGEPOLICY);
|
||||
CBaseAnimatedVariable(const CBaseAnimatedVariable&) = delete;
|
||||
CBaseAnimatedVariable(CBaseAnimatedVariable&&) = delete;
|
||||
CBaseAnimatedVariable& operator=(const CBaseAnimatedVariable&) = delete;
|
||||
CBaseAnimatedVariable& operator=(CBaseAnimatedVariable&&) = delete;
|
||||
|
||||
CAnimatedVariable(const CAnimatedVariable&) = delete;
|
||||
CAnimatedVariable(CAnimatedVariable&&) = delete;
|
||||
CAnimatedVariable& operator=(const CAnimatedVariable&) = delete;
|
||||
CAnimatedVariable& operator=(CAnimatedVariable&&) = delete;
|
||||
|
||||
~CAnimatedVariable();
|
||||
virtual ~CBaseAnimatedVariable();
|
||||
|
||||
void unregister();
|
||||
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();
|
||||
}
|
||||
virtual void warp(bool endCallback = true) = 0;
|
||||
|
||||
//
|
||||
void setConfig(SAnimationPropertyConfig* pConfig) {
|
||||
m_pConfig = pConfig;
|
||||
}
|
||||
|
@ -212,6 +97,11 @@ class CAnimatedVariable {
|
|||
/* returns the current curve value */
|
||||
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.
|
||||
if an animation is not running, runs instantly.
|
||||
if "remove" is set to true, will remove the callback when ran. */
|
||||
|
@ -245,20 +135,7 @@ class CAnimatedVariable {
|
|||
m_bRemoveEndAfterRan = false;
|
||||
}
|
||||
|
||||
private:
|
||||
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
|
||||
protected:
|
||||
void* m_pWindow = nullptr;
|
||||
void* m_pWorkspace = nullptr;
|
||||
void* m_pLayer = nullptr;
|
||||
|
@ -271,8 +148,8 @@ class CAnimatedVariable {
|
|||
|
||||
std::chrono::system_clock::time_point animationBegin;
|
||||
|
||||
ANIMATEDVARTYPE m_eVarType = AVARTYPE_INVALID;
|
||||
AVARDAMAGEPOLICY m_eDamagePolicy = AVARDAMAGE_NONE;
|
||||
ANIMATEDVARTYPE m_Type;
|
||||
|
||||
bool m_bRemoveEndAfterRan = true;
|
||||
bool m_bRemoveBeginAfterRan = true;
|
||||
|
@ -281,7 +158,9 @@ class CAnimatedVariable {
|
|||
std::function<void(void* thisptr)> m_fUpdateCallback;
|
||||
|
||||
bool m_bIsConnectedToActive = false;
|
||||
|
||||
void connectToActive();
|
||||
|
||||
void disconnectFromActive();
|
||||
|
||||
// methods
|
||||
|
@ -314,3 +193,85 @@ class CAnimatedVariable {
|
|||
friend struct SLayerSurface;
|
||||
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 <limits>
|
||||
#include <algorithm>
|
||||
|
||||
wlr_box CBox::wlr() {
|
||||
CBox rounded = roundInternal();
|
||||
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;
|
||||
}
|
||||
|
||||
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() {
|
||||
float newW = x + w - std::floor(x);
|
||||
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& addExtents(const SWindowDecorationExtents& e);
|
||||
CBox& expand(const double& value);
|
||||
CBox& noNegativeSize();
|
||||
|
||||
CBox copy() const;
|
||||
|
||||
|
@ -73,6 +74,8 @@ class CBox {
|
|||
double height;
|
||||
};
|
||||
|
||||
double rot = 0; /* rad, ccw */
|
||||
|
||||
//
|
||||
bool operator==(const CBox& rhs) const {
|
||||
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);
|
||||
}
|
||||
|
||||
void removeWLSignal(wl_listener* pListener) {
|
||||
wl_list_remove(&pListener->link);
|
||||
wl_list_init(&pListener->link);
|
||||
|
||||
Debug::log(LOG, "Removed listener {:x}", (uintptr_t)pListener);
|
||||
}
|
||||
|
||||
void handleNoop(struct wl_listener* listener, void* data) {
|
||||
// Do nothing
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ struct SCallstackFrameInfo {
|
|||
|
||||
std::string absolutePath(const std::string&, const std::string&);
|
||||
void addWLSignal(wl_signal*, wl_listener*, void* pOwner, const std::string& ownerString);
|
||||
void removeWLSignal(wl_listener*);
|
||||
std::string escapeJSONStrings(const std::string& str);
|
||||
std::string removeBeginEndSpacesTabs(std::string);
|
||||
bool isNumber(const std::string&, bool allowfloat = false);
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
#include "Monitor.hpp"
|
||||
|
||||
#include "MiscFunctions.hpp"
|
||||
|
||||
#include "../Compositor.hpp"
|
||||
|
||||
int ratHandler(void* data) {
|
||||
|
@ -8,7 +10,7 @@ int ratHandler(void* data) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
CMonitor::CMonitor() {
|
||||
CMonitor::CMonitor() : state(this) {
|
||||
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
|
||||
|
||||
if (m_bEnabled) {
|
||||
wlr_output_enable(output, 1);
|
||||
wlr_output_commit(output);
|
||||
wlr_output_state_set_enabled(state.wlr(), true);
|
||||
state.commit();
|
||||
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
|
||||
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))
|
||||
createdByUser = true; // should be true. WL, X11 and Headless backends should be addable / removable
|
||||
|
||||
// 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 (monitorRule.disabled) {
|
||||
|
||||
wlr_output_set_scale(output, 1);
|
||||
wlr_output_set_transform(output, WL_OUTPUT_TRANSFORM_NORMAL);
|
||||
wlr_output_state_set_scale(state.wlr(), 1);
|
||||
wlr_output_state_set_transform(state.wlr(), WL_OUTPUT_TRANSFORM_NORMAL);
|
||||
|
||||
auto PREFSTATE = wlr_output_preferred_mode(output);
|
||||
|
||||
|
@ -72,9 +78,9 @@ void CMonitor::onConnect(bool noRule) {
|
|||
wlr_output_mode* mode;
|
||||
|
||||
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;
|
||||
|
||||
PREFSTATE = mode;
|
||||
|
@ -83,13 +89,13 @@ void CMonitor::onConnect(bool noRule) {
|
|||
}
|
||||
|
||||
if (PREFSTATE)
|
||||
wlr_output_set_mode(output, PREFSTATE);
|
||||
wlr_output_state_set_mode(state.wlr(), PREFSTATE);
|
||||
else
|
||||
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);
|
||||
|
||||
m_bEnabled = false;
|
||||
|
@ -130,13 +136,28 @@ void CMonitor::onConnect(bool noRule) {
|
|||
|
||||
m_bEnabled = true;
|
||||
|
||||
wlr_output_enable(output, 1);
|
||||
wlr_output_state_set_enabled(state.wlr(), 1);
|
||||
|
||||
// set mode, also applies
|
||||
if (!noRule)
|
||||
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);
|
||||
|
||||
|
@ -162,6 +183,7 @@ void CMonitor::onConnect(bool noRule) {
|
|||
//
|
||||
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"monitoradded", szName});
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"monitoraddedv2", std::format("{},{},{}", ID, szName, szShortDescription)});
|
||||
EMIT_HOOK_EVENT("monitorAdded", this);
|
||||
|
||||
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)
|
||||
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)
|
||||
g_pCompositor->setActiveMonitor(BACKUPMON);
|
||||
|
@ -307,13 +330,11 @@ void CMonitor::onDisconnect(bool destroy) {
|
|||
}
|
||||
|
||||
void CMonitor::addDamage(const pixman_region32_t* rg) {
|
||||
static auto* const PZOOMFACTOR = &g_pConfigManager->getConfigValuePtr("misc:cursor_zoom_factor")->floatValue;
|
||||
if (*PZOOMFACTOR != 1.f && g_pCompositor->getMonitorFromCursor() == this) {
|
||||
static auto* const PZOOMFACTOR = (Hyprlang::FLOAT* const*)g_pConfigManager->getConfigValuePtr("misc:cursor_zoom_factor");
|
||||
if (**PZOOMFACTOR != 1.f && g_pCompositor->getMonitorFromCursor() == this) {
|
||||
wlr_damage_ring_add_whole(&damage);
|
||||
g_pCompositor->scheduleFrameForMonitor(this);
|
||||
}
|
||||
|
||||
if (wlr_damage_ring_add(&damage, rg))
|
||||
} else if (wlr_damage_ring_add(&damage, rg))
|
||||
g_pCompositor->scheduleFrameForMonitor(this);
|
||||
}
|
||||
|
||||
|
@ -322,8 +343,8 @@ void CMonitor::addDamage(const CRegion* rg) {
|
|||
}
|
||||
|
||||
void CMonitor::addDamage(const CBox* box) {
|
||||
static auto* const PZOOMFACTOR = &g_pConfigManager->getConfigValuePtr("misc:cursor_zoom_factor")->floatValue;
|
||||
if (*PZOOMFACTOR != 1.f && g_pCompositor->getMonitorFromCursor() == this) {
|
||||
static auto* const PZOOMFACTOR = (Hyprlang::FLOAT* const*)g_pConfigManager->getConfigValuePtr("misc:cursor_zoom_factor");
|
||||
if (**PZOOMFACTOR != 1.f && g_pCompositor->getMonitorFromCursor() == this) {
|
||||
wlr_damage_ring_add_whole(&damage);
|
||||
g_pCompositor->scheduleFrameForMonitor(this);
|
||||
}
|
||||
|
@ -336,6 +357,19 @@ bool CMonitor::isMirror() {
|
|||
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() {
|
||||
for (size_t i = 1; i < INT32_MAX; ++i) {
|
||||
if (g_pCompositor->getWorkspaceByID(i))
|
||||
|
@ -415,7 +449,7 @@ void CMonitor::setMirror(const std::string& mirrorOf) {
|
|||
pMirrorOf = nullptr;
|
||||
|
||||
// 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;
|
||||
|
||||
|
@ -502,7 +536,7 @@ float CMonitor::getDefaultScale() {
|
|||
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)
|
||||
return;
|
||||
|
||||
|
@ -533,13 +567,13 @@ void CMonitor::changeWorkspace(CWorkspace* const pWorkspace, bool internal, bool
|
|||
}
|
||||
}
|
||||
|
||||
if (!g_pCompositor->m_pLastMonitor->specialWorkspaceID) {
|
||||
static auto* const PFOLLOWMOUSE = &g_pConfigManager->getConfigValuePtr("input:follow_mouse")->intValue;
|
||||
if (!noFocus && !g_pCompositor->m_pLastMonitor->specialWorkspaceID) {
|
||||
static auto* const PFOLLOWMOUSE = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("input:follow_mouse");
|
||||
CWindow* pWindow = pWorkspace->getLastFocusedWindow();
|
||||
|
||||
if (!pWindow) {
|
||||
if (*PFOLLOWMOUSE == 1)
|
||||
pWindow = g_pCompositor->vectorToWindowIdeal(g_pInputManager->getMouseCoordsInternal());
|
||||
if (**PFOLLOWMOUSE == 1)
|
||||
pWindow = g_pCompositor->vectorToWindowUnified(g_pInputManager->getMouseCoordsInternal(), RESERVED_EXTENTS | INPUT_EXTENTS | ALLOW_FLOATING);
|
||||
|
||||
if (!pWindow)
|
||||
pWindow = g_pCompositor->getTopLeftWindowOnWorkspace(pWorkspace->m_iID);
|
||||
|
@ -569,8 +603,8 @@ void CMonitor::changeWorkspace(CWorkspace* const pWorkspace, bool internal, bool
|
|||
g_pCompositor->updateSuspendedStates();
|
||||
}
|
||||
|
||||
void CMonitor::changeWorkspace(const int& id, bool internal) {
|
||||
changeWorkspace(g_pCompositor->getWorkspaceByID(id), internal);
|
||||
void CMonitor::changeWorkspace(const int& id, bool internal, bool noMouseMove, bool noFocus) {
|
||||
changeWorkspace(g_pCompositor->getWorkspaceByID(id), internal, noMouseMove, noFocus);
|
||||
}
|
||||
|
||||
void CMonitor::setSpecialWorkspace(CWorkspace* const pWorkspace) {
|
||||
|
@ -621,17 +655,17 @@ void CMonitor::setSpecialWorkspace(CWorkspace* const pWorkspace) {
|
|||
for (auto& w : g_pCompositor->m_vWindows) {
|
||||
if (w->m_iWorkspaceID == pWorkspace->m_iID) {
|
||||
w->m_iMonitorID = ID;
|
||||
w->updateSurfaceOutputs();
|
||||
w->updateSurfaceScaleTransformDetails();
|
||||
|
||||
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 it's floating and the middle isnt on the current mon, move it to the center
|
||||
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,
|
||||
PMONFROMMIDDLE->vecPosition.y + PMONFROMMIDDLE->vecSize.y)) {
|
||||
// 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
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
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 {
|
||||
public:
|
||||
CMonitor();
|
||||
|
@ -45,12 +64,15 @@ class CMonitor {
|
|||
|
||||
std::string szName = "";
|
||||
std::string szDescription = "";
|
||||
std::string szShortDescription = "";
|
||||
|
||||
Vector2D vecReservedTopLeft = Vector2D(0, 0);
|
||||
Vector2D vecReservedBottomRight = Vector2D(0, 0);
|
||||
|
||||
drmModeModeInfo customDrmMode = {};
|
||||
|
||||
CMonitorState state;
|
||||
|
||||
// WLR stuff
|
||||
wlr_damage_ring damage;
|
||||
wlr_output* output = nullptr;
|
||||
|
@ -63,6 +85,7 @@ class CMonitor {
|
|||
bool gammaChanged = false;
|
||||
float xwaylandScale = 1.f;
|
||||
std::array<float, 9> projMatrix = {0};
|
||||
std::optional<Vector2D> forceSize;
|
||||
|
||||
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.
|
||||
|
@ -84,8 +107,6 @@ class CMonitor {
|
|||
CMonitor* pMirrorOf = nullptr;
|
||||
std::vector<CMonitor*> mirrors;
|
||||
|
||||
CRegion lastFrameDamage; // stores last frame damage
|
||||
|
||||
// for tearing
|
||||
CWindow* solitaryClient = nullptr;
|
||||
|
||||
|
@ -119,9 +140,10 @@ class CMonitor {
|
|||
void addDamage(const CBox* box);
|
||||
void setMirror(const std::string&);
|
||||
bool isMirror();
|
||||
bool matchesStaticSelector(const std::string& selector) const;
|
||||
float getDefaultScale();
|
||||
void changeWorkspace(CWorkspace* const pWorkspace, bool internal = false, bool noMouseMove = false);
|
||||
void changeWorkspace(const int& id, bool internal = false);
|
||||
void changeWorkspace(CWorkspace* const pWorkspace, bool internal = false, bool noMouseMove = false, bool noFocus = false);
|
||||
void changeWorkspace(const int& id, bool internal = false, bool noMouseMove = false, bool noFocus = false);
|
||||
void setSpecialWorkspace(CWorkspace* const pWorkspace);
|
||||
void setSpecialWorkspace(const int& id);
|
||||
void moveTo(const Vector2D& pos);
|
||||
|
|
|
@ -112,6 +112,11 @@ CRegion& CRegion::scale(float scale) {
|
|||
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> result;
|
||||
|
||||
|
|
|
@ -49,6 +49,7 @@ class CRegion {
|
|||
CRegion& invert(pixman_box32_t* box);
|
||||
CRegion& invert(const CBox& box);
|
||||
CRegion& scale(float scale);
|
||||
CRegion& scale(const Vector2D& scale);
|
||||
CBox getExtents();
|
||||
bool containsPoint(const Vector2D& vec) const;
|
||||
bool empty() const;
|
||||
|
@ -57,6 +58,7 @@ class CRegion {
|
|||
|
||||
std::vector<pixman_box32_t> getRects() const;
|
||||
|
||||
//
|
||||
pixman_region32_t* pixman() {
|
||||
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.",
|
||||
"To rice, or not to rice, that is the question.",
|
||||
"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
|
||||
"J'remue le ciel, le jour, la nuit.",
|
||||
"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.",
|
||||
"Take on me, take me on...",
|
||||
"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",
|
||||
"Say no way, say no way ya, no way!",
|
||||
"Ground control to Major Tom...",
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
Vector2D::Vector2D(const Hyprlang::VEC2& ref) {
|
||||
x = ref.x;
|
||||
y = ref.y;
|
||||
}
|
||||
|
||||
Vector2D::~Vector2D() {}
|
||||
|
||||
double Vector2D::normalize() {
|
||||
|
@ -42,14 +47,10 @@ double Vector2D::distance(const Vector2D& other) const {
|
|||
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 {
|
||||
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 <format>
|
||||
#include "../macros.hpp"
|
||||
#include <hyprlang.hpp>
|
||||
|
||||
class Vector2D {
|
||||
public:
|
||||
Vector2D(double, double);
|
||||
Vector2D();
|
||||
~Vector2D();
|
||||
Vector2D(const Hyprlang::VEC2&);
|
||||
|
||||
double x = 0;
|
||||
double y = 0;
|
||||
|
@ -88,12 +90,12 @@ class Vector2D {
|
|||
|
||||
double distance(const Vector2D& other) 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 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"
|
||||
|
||||
SLayerSurface::SLayerSurface() {
|
||||
alpha.create(AVARTYPE_FLOAT, g_pConfigManager->getAnimationPropertyConfig("fadeIn"), nullptr, AVARDAMAGE_ENTIRE);
|
||||
alpha.create(g_pConfigManager->getAnimationPropertyConfig("fadeLayers"), nullptr, AVARDAMAGE_ENTIRE);
|
||||
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();
|
||||
realPosition.registerVar();
|
||||
realSize.registerVar();
|
||||
|
||||
alpha.setValueAndWarp(0.f);
|
||||
}
|
||||
|
||||
SLayerSurface::~SLayerSurface() {
|
||||
|
@ -22,6 +30,7 @@ void SLayerSurface::applyRules() {
|
|||
ignoreAlpha = false;
|
||||
ignoreAlphaValue = 0.f;
|
||||
xray = -1;
|
||||
animationStyle.reset();
|
||||
|
||||
for (auto& rule : g_pConfigManager->getMatchingRules(this)) {
|
||||
if (rule.rule == "noanim")
|
||||
|
@ -44,10 +53,120 @@ void SLayerSurface::applyRules() {
|
|||
try {
|
||||
xray = configStringToInt(vars[1]);
|
||||
} 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 result;
|
||||
|
||||
|
@ -62,11 +181,11 @@ CRegion SConstraint::getLogicCoordsRegion() {
|
|||
result.add(&constraint->region); // surface-local coords
|
||||
|
||||
if (!PWINDOWOWNER->m_bIsX11) {
|
||||
result.translate(PWINDOWOWNER->m_vRealPosition.goalv());
|
||||
result.translate(PWINDOWOWNER->m_vRealPosition.goal());
|
||||
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});
|
||||
|
||||
const auto PMONITOR = PWINDOWOWNER->m_bIsMapped ? g_pCompositor->getMonitorFromID(PWINDOWOWNER->m_iMonitorID) : g_pCompositor->getMonitorFromVector(COORDS);
|
||||
|
@ -91,9 +210,9 @@ Vector2D SConstraint::getLogicConstraintPos() {
|
|||
return {};
|
||||
|
||||
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});
|
||||
|
||||
return COORDS;
|
||||
|
@ -109,7 +228,7 @@ Vector2D SConstraint::getLogicConstraintSize() {
|
|||
return {};
|
||||
|
||||
if (!PWINDOWOWNER->m_bIsX11)
|
||||
return PWINDOWOWNER->m_vRealSize.goalv();
|
||||
return PWINDOWOWNER->m_vRealSize.goal();
|
||||
|
||||
const auto PMONITOR = PWINDOWOWNER->m_bIsMapped ?
|
||||
g_pCompositor->getMonitorFromID(PWINDOWOWNER->m_iMonitorID) :
|
||||
|
@ -118,8 +237,72 @@ Vector2D SConstraint::getLogicConstraintSize() {
|
|||
if (!PMONITOR)
|
||||
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;
|
||||
|
||||
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 "wlr-layer-shell-unstable-v1-protocol.h"
|
||||
#include "../Window.hpp"
|
||||
#include "SubsurfaceTree.hpp"
|
||||
#include "../desktop/Subsurface.hpp"
|
||||
#include "../desktop/Popup.hpp"
|
||||
#include "AnimatedVariable.hpp"
|
||||
#include "WLSurface.hpp"
|
||||
#include "../desktop/WLSurface.hpp"
|
||||
#include "Region.hpp"
|
||||
|
||||
struct SLayerRule {
|
||||
|
@ -19,6 +20,11 @@ struct SLayerSurface {
|
|||
~SLayerSurface();
|
||||
|
||||
void applyRules();
|
||||
void startAnimation(bool in, bool instant = false);
|
||||
bool isFadedOut();
|
||||
|
||||
CAnimatedVariable<Vector2D> realPosition;
|
||||
CAnimatedVariable<Vector2D> realSize;
|
||||
|
||||
wlr_layer_surface_v1* layerSurface;
|
||||
wl_list link;
|
||||
|
@ -26,13 +32,14 @@ struct SLayerSurface {
|
|||
bool keyboardExclusive = false;
|
||||
|
||||
CWLSurface surface;
|
||||
std::list<CWLSurface> popupSurfaces;
|
||||
|
||||
// desktop components
|
||||
std::unique_ptr<CPopup> popupHead;
|
||||
|
||||
DYNLISTENER(destroyLayerSurface);
|
||||
DYNLISTENER(mapLayerSurface);
|
||||
DYNLISTENER(unmapLayerSurface);
|
||||
DYNLISTENER(commitLayerSurface);
|
||||
DYNLISTENER(newPopup);
|
||||
|
||||
CBox geometry = {0, 0, 0, 0};
|
||||
Vector2D position;
|
||||
|
@ -44,7 +51,7 @@ struct SLayerSurface {
|
|||
|
||||
std::string szNamespace = "";
|
||||
|
||||
CAnimatedVariable alpha;
|
||||
CAnimatedVariable<float> alpha;
|
||||
bool fadingOut = false;
|
||||
bool readyToDelete = false;
|
||||
bool noProcess = false;
|
||||
|
@ -55,6 +62,8 @@ struct SLayerSurface {
|
|||
bool ignoreAlpha = false;
|
||||
float ignoreAlphaValue = 0.f;
|
||||
|
||||
std::optional<std::string> animationStyle;
|
||||
|
||||
// For the list lookup
|
||||
bool operator==(const SLayerSurface& rhs) const {
|
||||
return layerSurface == rhs.layerSurface && monitorID == rhs.monitorID;
|
||||
|
@ -128,6 +137,7 @@ struct SKeyboard {
|
|||
bool enabled = true;
|
||||
|
||||
xkb_layout_index_t activeLayout = 0;
|
||||
xkb_state* xkbTranslationState = nullptr;
|
||||
|
||||
std::string name = "";
|
||||
std::string xkbFilePath = "";
|
||||
|
@ -136,6 +146,9 @@ struct SKeyboard {
|
|||
int repeatRate = 0;
|
||||
int repeatDelay = 0;
|
||||
int numlockOn = -1;
|
||||
bool resolveBindsBySym = false;
|
||||
|
||||
void updateXKBTranslationState(xkb_keymap* const keymap = nullptr);
|
||||
|
||||
// For the list lookup
|
||||
bool operator==(const SKeyboard& rhs) const {
|
||||
|
@ -190,34 +203,6 @@ struct SConstraint {
|
|||
|
||||
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 {
|
||||
wlr_seat* seat = nullptr;
|
||||
wl_client* exclusiveClient = nullptr;
|
||||
|
@ -259,6 +244,8 @@ struct STablet {
|
|||
|
||||
std::string name = "";
|
||||
|
||||
std::string boundOutput = "";
|
||||
|
||||
//
|
||||
bool operator==(const STablet& b) const {
|
||||
return wlrDevice == b.wlrDevice;
|
||||
|
@ -406,7 +393,17 @@ struct STearingController {
|
|||
DYNLISTENER(set);
|
||||
DYNLISTENER(destroy);
|
||||
|
||||
bool operator==(const STearingController& other) {
|
||||
bool operator==(const STearingController& other) const {
|
||||
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,12 +7,14 @@
|
|||
void handleWrapped(wl_listener* listener, void* data) {
|
||||
CHyprWLListener::SWrapper* pWrap = wl_container_of(listener, pWrap, m_sListener);
|
||||
|
||||
if (g_pWatchdog)
|
||||
g_pWatchdog->startWatching();
|
||||
|
||||
try {
|
||||
pWrap->m_pSelf->emit(data);
|
||||
} catch (std::exception& e) { Debug::log(ERR, "Listener {} timed out and was killed by Watchdog!!!", (uintptr_t)listener); }
|
||||
|
||||
if (g_pWatchdog)
|
||||
g_pWatchdog->endWatching();
|
||||
}
|
||||
|
||||
|
|
|
@ -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_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) {
|
||||
std::unique_lock lk(m_mWatchdogMutex);
|
||||
|
@ -21,7 +21,7 @@ CWatchdog::CWatchdog() {
|
|||
if (!m_bWillWatch)
|
||||
m_cvWatchdogCondition.wait(lk, [this] { return m_bNotified; });
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -37,9 +37,9 @@ CWatchdog::CWatchdog() {
|
|||
}
|
||||
|
||||
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;
|
||||
|
||||
m_tTriggered = std::chrono::high_resolution_clock::now();
|
||||
|
|
|
@ -139,7 +139,7 @@ void CHyprError::draw() {
|
|||
|
||||
if (m_bQueuedDestroy) {
|
||||
if (!m_fFadeOpacity.isBeingAnimated()) {
|
||||
if (m_fFadeOpacity.fl() == 0.f) {
|
||||
if (m_fFadeOpacity.value() == 0.f) {
|
||||
m_bQueuedDestroy = false;
|
||||
m_tTexture.destroyTexture();
|
||||
m_bIsCreated = false;
|
||||
|
@ -164,7 +164,7 @@ void CHyprError::draw() {
|
|||
|
||||
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() {
|
||||
|
|
|
@ -22,7 +22,7 @@ class CHyprError {
|
|||
bool m_bQueuedDestroy = false;
|
||||
bool m_bIsCreated = false;
|
||||
CTexture m_tTexture;
|
||||
CAnimatedVariable m_fFadeOpacity;
|
||||
CAnimatedVariable<float> m_fFadeOpacity;
|
||||
CBox m_bDamageBox = {0, 0, 0, 0};
|
||||
|
||||
bool m_bMonitorChanged = false;
|
||||
|
|
|
@ -4,13 +4,12 @@
|
|||
|
||||
void SDwindleNodeData::recalcSizePosRecursive(bool force, bool horizontalOverride, bool verticalOverride) {
|
||||
if (children[0]) {
|
||||
static auto* const PSMARTSPLIT = &g_pConfigManager->getConfigValuePtr("dwindle:smart_split")->intValue;
|
||||
static auto* const PPRESERVESPLIT = &g_pConfigManager->getConfigValuePtr("dwindle:preserve_split")->intValue;
|
||||
static auto* const PFLMULT = &g_pConfigManager->getConfigValuePtr("dwindle:split_width_multiplier")->floatValue;
|
||||
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");
|
||||
|
||||
if (*PPRESERVESPLIT == 0 && *PSMARTSPLIT == 0) {
|
||||
splitTop = box.h * *PFLMULT > box.w;
|
||||
}
|
||||
if (**PPRESERVESPLIT == 0 && **PSMARTSPLIT == 0)
|
||||
splitTop = box.h * **PFLMULT > box.w;
|
||||
|
||||
if (verticalOverride == true)
|
||||
splitTop = true;
|
||||
|
@ -22,13 +21,13 @@ void SDwindleNodeData::recalcSizePosRecursive(bool force, bool horizontalOverrid
|
|||
if (SPLITSIDE) {
|
||||
// split left/right
|
||||
const float FIRSTSIZE = box.w / 2.0 * splitRatio;
|
||||
children[0]->box = CBox{box.x, box.y, FIRSTSIZE, box.h};
|
||||
children[1]->box = CBox{box.x + FIRSTSIZE, box.y, box.w - 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}.noNegativeSize();
|
||||
} else {
|
||||
// split top/bottom
|
||||
const float FIRSTSIZE = box.h / 2.0 * splitRatio;
|
||||
children[0]->box = CBox{box.x, box.y, box.w, FIRSTSIZE};
|
||||
children[1]->box = CBox{box.x, box.y + FIRSTSIZE, box.w, box.h - 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}.noNegativeSize();
|
||||
}
|
||||
|
||||
children[0]->recalcSizePosRecursive(force);
|
||||
|
@ -64,6 +63,21 @@ SDwindleNodeData* CHyprDwindleLayout::getFirstNodeOnWorkspace(const int& id) {
|
|||
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) {
|
||||
for (auto& n : m_lDwindleNodesData) {
|
||||
if (n.pWindow == pWindow && !n.isNode)
|
||||
|
@ -113,26 +127,28 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for
|
|||
const auto PWINDOW = pNode->pWindow;
|
||||
// get specific gaps and rules for this workspace,
|
||||
// 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)
|
||||
return;
|
||||
|
||||
PWINDOW->updateSpecialRenderData();
|
||||
|
||||
static auto* const PGAPSIN = &g_pConfigManager->getConfigValuePtr("general:gaps_in")->intValue;
|
||||
static auto* const PGAPSOUT = &g_pConfigManager->getConfigValuePtr("general:gaps_out")->intValue;
|
||||
static auto* const PNOGAPSWHENONLY = &g_pConfigManager->getConfigValuePtr("dwindle:no_gaps_when_only")->intValue;
|
||||
static auto* const PNOGAPSWHENONLY = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("dwindle:no_gaps_when_only");
|
||||
static auto* const PGAPSINDATA = (Hyprlang::CUSTOMTYPE* const*)g_pConfigManager->getConfigValuePtr("general:gaps_in");
|
||||
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 gapsOut = WORKSPACERULE.gapsOut.value_or(*PGAPSOUT);
|
||||
|
||||
if (!g_pCompositor->windowExists(PWINDOW) || !PWINDOW->m_bIsMapped) {
|
||||
Debug::log(ERR, "Node {} holding invalid {}!!", pNode, PWINDOW);
|
||||
onWindowRemovedTiling(PWINDOW);
|
||||
return;
|
||||
}
|
||||
|
||||
CBox nodeBox = pNode->box;
|
||||
nodeBox.round();
|
||||
|
||||
|
@ -141,10 +157,10 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for
|
|||
|
||||
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))) {
|
||||
|
||||
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.rounding = 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_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;
|
||||
}
|
||||
|
@ -164,9 +180,9 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for
|
|||
auto calcPos = PWINDOW->m_vPosition;
|
||||
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;
|
||||
calcSize = calcSize - OFFSETTOPLEFT - OFFSETBOTTOMRIGHT;
|
||||
|
@ -201,9 +217,9 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for
|
|||
|
||||
if (g_pCompositor->isWorkspaceSpecial(PWINDOW->m_iWorkspaceID)) {
|
||||
// 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
|
||||
|
||||
PWINDOW->m_vRealPosition = wb.pos();
|
||||
|
@ -211,10 +227,13 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for
|
|||
|
||||
g_pXWaylandManager->setWindowSize(PWINDOW, wb.size());
|
||||
} else {
|
||||
PWINDOW->m_vRealSize = calcSize;
|
||||
PWINDOW->m_vRealPosition = calcPos;
|
||||
CBox wb = {calcPos, calcSize};
|
||||
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) {
|
||||
|
@ -238,8 +257,8 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection dire
|
|||
|
||||
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 PDEFAULTSPLIT = &g_pConfigManager->getConfigValuePtr("dwindle:default_split_ratio")->floatValue;
|
||||
static auto* const PUSEACTIVE = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("dwindle:use_active_for_splits");
|
||||
static auto* const PDEFAULTSPLIT = (Hyprlang::FLOAT* const*)g_pConfigManager->getConfigValuePtr("dwindle:default_split_ratio");
|
||||
|
||||
if (direction != DIRECTION_DEFAULT && overrideDirection == DIRECTION_DEFAULT)
|
||||
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 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 &&
|
||||
(PNODE->workspaceID == PMONITOR->activeWorkspace || (g_pCompositor->isWorkspaceSpecial(PNODE->workspaceID) && PMONITOR->specialWorkspaceID)) && !*PUSEACTIVE) {
|
||||
OPENINGON = getNodeFromWindow(g_pCompositor->vectorToWindowTiled(TARGETCOORDS));
|
||||
(PNODE->workspaceID == PMONITOR->activeWorkspace || (g_pCompositor->isWorkspaceSpecial(PNODE->workspaceID) && PMONITOR->specialWorkspaceID)) && !**PUSEACTIVE) {
|
||||
OPENINGON = getNodeFromWindow(g_pCompositor->vectorToWindowUnified(MOUSECOORDS, RESERVED_EXTENTS | INPUT_EXTENTS));
|
||||
|
||||
// happens on reserved area
|
||||
if (!OPENINGON && g_pCompositor->getWindowsOnWorkspace(PNODE->workspaceID) > 0)
|
||||
OPENINGON = getFirstNodeOnWorkspace(PMONITOR->activeWorkspace);
|
||||
if (!OPENINGON && g_pCompositor->isPointOnReservedArea(MOUSECOORDS, PMONITOR))
|
||||
OPENINGON = getClosestNodeOnWorkspace(PNODE->workspaceID, MOUSECOORDS);
|
||||
|
||||
} else if (*PUSEACTIVE) {
|
||||
} else if (**PUSEACTIVE) {
|
||||
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) {
|
||||
OPENINGON = getNodeFromWindow(g_pCompositor->m_pLastWindow);
|
||||
} 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)
|
||||
OPENINGON = getFirstNodeOnWorkspace(PMONITOR->activeWorkspace);
|
||||
if (!OPENINGON && g_pCompositor->isPointOnReservedArea(MOUSECOORDS, PMONITOR))
|
||||
OPENINGON = getClosestNodeOnWorkspace(PNODE->workspaceID, MOUSECOORDS);
|
||||
|
||||
} else
|
||||
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
|
||||
m_lDwindleNodesData.remove(*PNODE);
|
||||
|
||||
static const auto* USECURRPOS = &g_pConfigManager->getConfigValuePtr("group:insert_after_current")->intValue;
|
||||
(*USECURRPOS ? OPENINGON->pWindow : OPENINGON->pWindow->getGroupTail())->insertWindowToGroup(pWindow);
|
||||
static const auto* USECURRPOS = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("group:insert_after_current");
|
||||
(**USECURRPOS ? OPENINGON->pWindow : OPENINGON->pWindow->getGroupTail())->insertWindowToGroup(pWindow);
|
||||
|
||||
OPENINGON->pWindow->setGroupCurrent(pWindow);
|
||||
pWindow->applyGroupRules();
|
||||
|
@ -349,17 +367,17 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection dire
|
|||
NEWPARENT->workspaceID = OPENINGON->workspaceID;
|
||||
NEWPARENT->pParent = OPENINGON->pParent;
|
||||
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
|
||||
const auto SIDEBYSIDE = NEWPARENT->box.w > NEWPARENT->box.h * *PWIDTHMULTIPLIER;
|
||||
const auto SIDEBYSIDE = NEWPARENT->box.w > NEWPARENT->box.h * **PWIDTHMULTIPLIER;
|
||||
NEWPARENT->splitTop = !SIDEBYSIDE;
|
||||
|
||||
static auto* const PFORCESPLIT = &g_pConfigManager->getConfigValuePtr("dwindle:force_split")->intValue;
|
||||
static auto* const PERMANENTDIRECTIONOVERRIDE = &g_pConfigManager->getConfigValuePtr("dwindle:permanent_direction_override")->intValue;
|
||||
static auto* const PSMARTSPLIT = &g_pConfigManager->getConfigValuePtr("dwindle:smart_split")->intValue;
|
||||
static auto* const PFORCESPLIT = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("dwindle:force_split");
|
||||
static auto* const PERMANENTDIRECTIONOVERRIDE = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("dwindle:permanent_direction_override");
|
||||
static auto* const PSMARTSPLIT = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("dwindle:smart_split");
|
||||
|
||||
bool horizontalOverride = 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
|
||||
if (*PERMANENTDIRECTIONOVERRIDE == 0)
|
||||
if (**PERMANENTDIRECTIONOVERRIDE == 0)
|
||||
overrideDirection = DIRECTION_DEFAULT;
|
||||
} else if (*PSMARTSPLIT == 1) {
|
||||
const auto tl = NEWPARENT->box.pos();
|
||||
const auto tr = NEWPARENT->box.pos() + Vector2D(NEWPARENT->box.w, 0);
|
||||
const auto bl = NEWPARENT->box.pos() + Vector2D(0, NEWPARENT->box.h);
|
||||
const auto br = NEWPARENT->box.pos() + NEWPARENT->box.size();
|
||||
const auto cc = NEWPARENT->box.pos() + NEWPARENT->box.size() / 2;
|
||||
} else if (**PSMARTSPLIT == 1) {
|
||||
const auto PARENT_CENTER = NEWPARENT->box.pos() + NEWPARENT->box.size() / 2;
|
||||
const auto PARENT_PROPORTIONS = NEWPARENT->box.h / NEWPARENT->box.w;
|
||||
const auto DELTA = MOUSECOORDS - PARENT_CENTER;
|
||||
const auto DELTA_SLOPE = DELTA.y / DELTA.x;
|
||||
|
||||
if (TARGETCOORDS.inTriangle(tl, tr, cc)) {
|
||||
NEWPARENT->splitTop = true;
|
||||
NEWPARENT->children[0] = PNODE;
|
||||
NEWPARENT->children[1] = OPENINGON;
|
||||
} else if (TARGETCOORDS.inTriangle(tr, cc, br)) {
|
||||
if (abs(DELTA_SLOPE) < PARENT_PROPORTIONS) {
|
||||
if (DELTA.x > 0) {
|
||||
// right
|
||||
NEWPARENT->splitTop = false;
|
||||
NEWPARENT->children[0] = OPENINGON;
|
||||
NEWPARENT->children[1] = PNODE;
|
||||
} else if (TARGETCOORDS.inTriangle(br, bl, cc)) {
|
||||
NEWPARENT->splitTop = true;
|
||||
NEWPARENT->children[0] = OPENINGON;
|
||||
NEWPARENT->children[1] = PNODE;
|
||||
} else {
|
||||
// left
|
||||
NEWPARENT->splitTop = false;
|
||||
NEWPARENT->children[0] = PNODE;
|
||||
NEWPARENT->children[1] = OPENINGON;
|
||||
}
|
||||
} else if (*PFORCESPLIT == 0 || !pWindow->m_bFirstMap) {
|
||||
} else {
|
||||
if (DELTA.y > 0) {
|
||||
// bottom
|
||||
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) {
|
||||
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 &&
|
||||
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.
|
||||
NEWPARENT->children[1] = OPENINGON;
|
||||
NEWPARENT->children[0] = PNODE;
|
||||
|
@ -423,7 +448,7 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection dire
|
|||
NEWPARENT->children[1] = PNODE;
|
||||
}
|
||||
} else {
|
||||
if (*PFORCESPLIT == 1) {
|
||||
if (**PFORCESPLIT == 1) {
|
||||
NEWPARENT->children[1] = OPENINGON;
|
||||
NEWPARENT->children[0] = PNODE;
|
||||
} else {
|
||||
|
@ -442,7 +467,7 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection dire
|
|||
}
|
||||
|
||||
// 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
|
||||
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)};
|
||||
|
@ -581,13 +606,13 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorn
|
|||
const auto PNODE = getNodeFromWindow(PWINDOW);
|
||||
|
||||
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();
|
||||
return;
|
||||
}
|
||||
|
||||
const auto PANIMATE = &g_pConfigManager->getConfigValuePtr("misc:animate_manual_resizes")->intValue;
|
||||
const auto PSMARTRESIZING = &g_pConfigManager->getConfigValuePtr("dwindle:smart_resizing")->intValue;
|
||||
const auto PANIMATE = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("misc:animate_manual_resizes");
|
||||
const auto PSMARTRESIZING = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("dwindle:smart_resizing");
|
||||
|
||||
// get some data about our window
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID);
|
||||
|
@ -600,7 +625,7 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorn
|
|||
if (!m_PseudoDragFlags.started) {
|
||||
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)));
|
||||
|
||||
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
|
||||
PWINDOW->m_vPseudoSize.y -= pixResize.y * 2;
|
||||
|
||||
PWINDOW->m_vPseudoSize.x = std::clamp(PWINDOW->m_vPseudoSize.x, 30.0, PNODE->box.w);
|
||||
PWINDOW->m_vPseudoSize.y = std::clamp(PWINDOW->m_vPseudoSize.y, 30.0, PNODE->box.h);
|
||||
CBox wbox = PNODE->box;
|
||||
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;
|
||||
PNODE->recalcSizePosRecursive(*PANIMATE == 0);
|
||||
PNODE->recalcSizePosRecursive(**PANIMATE == 0);
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -642,7 +669,7 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorn
|
|||
if (DISPLAYBOTTOM && DISPLAYTOP)
|
||||
allowedMovement.y = 0;
|
||||
|
||||
if (*PSMARTRESIZING == 1) {
|
||||
if (**PSMARTRESIZING == 1) {
|
||||
// Identify inner and outer nodes for both directions
|
||||
SDwindleNodeData* PVOUTER = nullptr;
|
||||
SDwindleNodeData* PVINNER = nullptr;
|
||||
|
@ -676,14 +703,14 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorn
|
|||
|
||||
if (PHINNER) {
|
||||
const auto ORIGINAL = PHINNER->box.w;
|
||||
PHOUTER->pParent->recalcSizePosRecursive(*PANIMATE == 0);
|
||||
PHOUTER->pParent->recalcSizePosRecursive(**PANIMATE == 0);
|
||||
if (PHINNER->pParent->children[0] == PHINNER)
|
||||
PHINNER->pParent->splitRatio = std::clamp((ORIGINAL - allowedMovement.x) / PHINNER->pParent->box.w * 2.f, 0.1, 1.9);
|
||||
else
|
||||
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
|
||||
PHOUTER->pParent->recalcSizePosRecursive(*PANIMATE == 0);
|
||||
PHOUTER->pParent->recalcSizePosRecursive(**PANIMATE == 0);
|
||||
}
|
||||
|
||||
if (PVOUTER) {
|
||||
|
@ -691,14 +718,14 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorn
|
|||
|
||||
if (PVINNER) {
|
||||
const auto ORIGINAL = PVINNER->box.h;
|
||||
PVOUTER->pParent->recalcSizePosRecursive(*PANIMATE == 0);
|
||||
PVOUTER->pParent->recalcSizePosRecursive(**PANIMATE == 0);
|
||||
if (PVINNER->pParent->children[0] == PVINNER)
|
||||
PVINNER->pParent->splitRatio = std::clamp((ORIGINAL - allowedMovement.y) / PVINNER->pParent->box.h * 2.f, 0.1, 1.9);
|
||||
else
|
||||
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
|
||||
PVOUTER->pParent->recalcSizePosRecursive(*PANIMATE == 0);
|
||||
PVOUTER->pParent->recalcSizePosRecursive(**PANIMATE == 0);
|
||||
}
|
||||
} else {
|
||||
// get the correct containers to apply splitratio to
|
||||
|
@ -717,11 +744,11 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorn
|
|||
if (PARENTSIDEBYSIDE) {
|
||||
allowedMovement.x *= 2.f / PPARENT->box.w;
|
||||
PPARENT->splitRatio = std::clamp(PPARENT->splitRatio + allowedMovement.x, 0.1, 1.9);
|
||||
PPARENT->recalcSizePosRecursive(*PANIMATE == 0);
|
||||
PPARENT->recalcSizePosRecursive(**PANIMATE == 0);
|
||||
} else {
|
||||
allowedMovement.y *= 2.f / PPARENT->box.h;
|
||||
PPARENT->splitRatio = std::clamp(PPARENT->splitRatio + allowedMovement.y, 0.1, 1.9);
|
||||
PPARENT->recalcSizePosRecursive(*PANIMATE == 0);
|
||||
PPARENT->recalcSizePosRecursive(**PANIMATE == 0);
|
||||
}
|
||||
|
||||
return;
|
||||
|
@ -736,11 +763,11 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorn
|
|||
if (PARENTSIDEBYSIDE) {
|
||||
allowedMovement.x *= 2.f / PPARENT->box.w;
|
||||
PPARENT->splitRatio = std::clamp(PPARENT->splitRatio + allowedMovement.x, 0.1, 1.9);
|
||||
PPARENT->recalcSizePosRecursive(*PANIMATE == 0);
|
||||
PPARENT->recalcSizePosRecursive(**PANIMATE == 0);
|
||||
} else {
|
||||
allowedMovement.y *= 2.f / PPARENT->box.h;
|
||||
PPARENT->splitRatio = std::clamp(PPARENT->splitRatio + allowedMovement.y, 0.1, 1.9);
|
||||
PPARENT->recalcSizePosRecursive(*PANIMATE == 0);
|
||||
PPARENT->recalcSizePosRecursive(**PANIMATE == 0);
|
||||
}
|
||||
|
||||
return;
|
||||
|
@ -755,8 +782,8 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorn
|
|||
|
||||
SIDECONTAINER->splitRatio = std::clamp(SIDECONTAINER->splitRatio + allowedMovement.x, 0.1, 1.9);
|
||||
TOPCONTAINER->splitRatio = std::clamp(TOPCONTAINER->splitRatio + allowedMovement.y, 0.1, 1.9);
|
||||
SIDECONTAINER->recalcSizePosRecursive(*PANIMATE == 0);
|
||||
TOPCONTAINER->recalcSizePosRecursive(*PANIMATE == 0);
|
||||
SIDECONTAINER->recalcSizePosRecursive(**PANIMATE == 0);
|
||||
TOPCONTAINER->recalcSizePosRecursive(**PANIMATE == 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -776,10 +803,21 @@ void CHyprDwindleLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscree
|
|||
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.
|
||||
pWindow->m_bIsFullscreen = on;
|
||||
PWORKSPACE->m_bHasFullscreenWindow = !PWORKSPACE->m_bHasFullscreenWindow;
|
||||
|
||||
pWindow->updateDynamicRules();
|
||||
pWindow->updateWindowDecos();
|
||||
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"fullscreen", std::to_string((int)on)});
|
||||
EMIT_HOOK_EVENT("fullscreen", pWindow);
|
||||
|
||||
|
@ -800,14 +838,6 @@ void CHyprDwindleLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscree
|
|||
|
||||
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
|
||||
if (fullscreenMode == FULLSCREEN_FULL) {
|
||||
pWindow->m_vRealPosition = PMONITOR->vecPosition;
|
||||
|
@ -824,13 +854,13 @@ void CHyprDwindleLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscree
|
|||
pWindow->m_vPosition = fakeNode.box.pos();
|
||||
pWindow->m_vSize = fakeNode.box.size();
|
||||
|
||||
applyNodeDataToWindow(&fakeNode);
|
||||
applyNodeDataToWindow(&fakeNode, true);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
|
@ -967,6 +997,8 @@ std::any CHyprDwindleLayout::layoutMessage(SLayoutMessageHeader header, std::str
|
|||
const auto ARGS = CVarList(message, 0, ' ');
|
||||
if (ARGS[0] == "togglesplit") {
|
||||
toggleSplit(header.pWindow);
|
||||
} else if (ARGS[0] == "swapsplit") {
|
||||
swapSplit(header.pWindow);
|
||||
} else if (ARGS[0] == "preselect") {
|
||||
std::string direction = ARGS[1];
|
||||
|
||||
|
@ -1020,6 +1052,20 @@ void CHyprDwindleLayout::toggleSplit(CWindow* pWindow) {
|
|||
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) {
|
||||
const auto PNODE = getNodeFromWindow(from);
|
||||
|
||||
|
@ -1047,3 +1093,53 @@ void CHyprDwindleLayout::onEnable() {
|
|||
void CHyprDwindleLayout::onDisable() {
|
||||
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 std::string getLayoutName();
|
||||
virtual void replaceWindowDataWith(CWindow* from, CWindow* to);
|
||||
virtual Vector2D predictSizeForNewWindow();
|
||||
|
||||
virtual void onEnable();
|
||||
virtual void onDisable();
|
||||
|
@ -79,9 +80,11 @@ class CHyprDwindleLayout : public IHyprLayout {
|
|||
void applyNodeDataToWindow(SDwindleNodeData*, bool force = false);
|
||||
SDwindleNodeData* getNodeFromWindow(CWindow*);
|
||||
SDwindleNodeData* getFirstNodeOnWorkspace(const int&);
|
||||
SDwindleNodeData* getClosestNodeOnWorkspace(const int&, const Vector2D&);
|
||||
SDwindleNodeData* getMasterNodeOnWorkspace(const int&);
|
||||
|
||||
void toggleSplit(CWindow*);
|
||||
void swapSplit(CWindow*);
|
||||
|
||||
eDirection overrideDirection = DIRECTION_DEFAULT;
|
||||
|
||||
|
|
|
@ -87,7 +87,7 @@ void IHyprLayout::onWindowCreatedFloating(CWindow* pWindow) {
|
|||
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) {
|
||||
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
|
||||
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;
|
||||
|
||||
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)
|
||||
pWindow->m_vRealPosition = g_pXWaylandManager->xwaylandToWaylandCoords({pWindow->m_uSurface.xwayland->x, pWindow->m_uSurface.xwayland->y});
|
||||
else
|
||||
pWindow->m_vRealPosition = Vector2D(PMONITOR->vecPosition.x + (PMONITOR->vecSize.x - pWindow->m_vRealSize.goalv().x) / 2.f,
|
||||
PMONITOR->vecPosition.y + (PMONITOR->vecSize.y - pWindow->m_vRealSize.goalv().y) / 2.f);
|
||||
pWindow->m_vRealPosition = Vector2D(PMONITOR->vecPosition.x + (PMONITOR->vecSize.x - pWindow->m_vRealSize.goal().x) / 2.f,
|
||||
PMONITOR->vecPosition.y + (PMONITOR->vecSize.y - pWindow->m_vRealSize.goal().y) / 2.f);
|
||||
} else {
|
||||
pWindow->m_vRealPosition = Vector2D(PMONITOR->vecPosition.x + (PMONITOR->vecSize.x - pWindow->m_vRealSize.goalv().x) / 2.f,
|
||||
PMONITOR->vecPosition.y + (PMONITOR->vecSize.y - pWindow->m_vRealSize.goalv().y) / 2.f);
|
||||
pWindow->m_vRealPosition = Vector2D(PMONITOR->vecPosition.x + (PMONITOR->vecSize.x - pWindow->m_vRealSize.goal().x) / 2.f,
|
||||
PMONITOR->vecPosition.y + (PMONITOR->vecSize.y - pWindow->m_vRealSize.goal().y) / 2.f);
|
||||
}
|
||||
} else {
|
||||
// we respect the size.
|
||||
|
@ -151,8 +151,8 @@ void IHyprLayout::onWindowCreatedFloating(CWindow* pWindow) {
|
|||
}
|
||||
}
|
||||
|
||||
if (*PXWLFORCESCALEZERO && pWindow->m_bIsX11)
|
||||
pWindow->m_vRealSize = pWindow->m_vRealSize.goalv() / PMONITOR->scale;
|
||||
if (**PXWLFORCESCALEZERO && pWindow->m_bIsX11)
|
||||
pWindow->m_vRealSize = pWindow->m_vRealSize.goal() / PMONITOR->scale;
|
||||
|
||||
if (pWindow->m_bX11DoesntWantBorders || (pWindow->m_bIsX11 && pWindow->m_uSurface.xwayland->override_redirect)) {
|
||||
pWindow->m_vRealPosition.warp();
|
||||
|
@ -160,11 +160,11 @@ void IHyprLayout::onWindowCreatedFloating(CWindow* pWindow) {
|
|||
}
|
||||
|
||||
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);
|
||||
} else {
|
||||
pWindow->m_vPendingReportedSize = pWindow->m_vRealSize.goalv();
|
||||
pWindow->m_vPendingReportedSize = pWindow->m_vRealSize.goal();
|
||||
pWindow->m_vReportedSize = pWindow->m_vPendingReportedSize;
|
||||
}
|
||||
}
|
||||
|
@ -200,18 +200,18 @@ void IHyprLayout::onBeginDragWindow() {
|
|||
|
||||
if (!DRAGGINGWINDOW->m_bIsFloating) {
|
||||
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);
|
||||
DRAGGINGWINDOW->m_bIsFloating = 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_vBeginDragPositionXY = DRAGGINGWINDOW->m_vRealPosition.goalv();
|
||||
m_vBeginDragSizeXY = DRAGGINGWINDOW->m_vRealSize.goalv();
|
||||
m_vBeginDragPositionXY = DRAGGINGWINDOW->m_vRealPosition.goal();
|
||||
m_vBeginDragSizeXY = DRAGGINGWINDOW->m_vRealSize.goal();
|
||||
m_vLastDragXY = m_vBeginDragXY;
|
||||
|
||||
// get the grab corner
|
||||
|
@ -268,15 +268,15 @@ void IHyprLayout::onEndDragWindow() {
|
|||
} else if (g_pInputManager->dragMode == MBIND_MOVE) {
|
||||
g_pHyprRenderer->damageWindow(DRAGGINGWINDOW);
|
||||
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))
|
||||
return;
|
||||
|
||||
if (pWindow->m_sGroupData.pNextWindow && DRAGGINGWINDOW->canBeGroupedInto(pWindow)) {
|
||||
static const auto* USECURRPOS = &g_pConfigManager->getConfigValuePtr("group:insert_after_current")->intValue;
|
||||
(*USECURRPOS ? pWindow : pWindow->getGroupTail())->insertWindowToGroup(DRAGGINGWINDOW);
|
||||
static const auto* USECURRPOS = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("group:insert_after_current");
|
||||
(**USECURRPOS ? pWindow : pWindow->getGroupTail())->insertWindowToGroup(DRAGGINGWINDOW);
|
||||
pWindow->setGroupCurrent(DRAGGINGWINDOW);
|
||||
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 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 PANIMATE = &g_pConfigManager->getConfigValuePtr("misc:animate_manual_resizes")->intValue;
|
||||
static auto* const PANIMATEMOUSE = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("misc:animate_mouse_windowdragging");
|
||||
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) ||
|
||||
(std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - TIMER).count() <
|
||||
1000.0 / g_pHyprRenderer->m_pMostHzMonitor->refreshRate &&
|
||||
(*PANIMATEMOUSE || *PANIMATE)))
|
||||
1000.0 / g_pHyprRenderer->m_pMostHzMonitor->refreshRate))
|
||||
return;
|
||||
|
||||
TIMER = std::chrono::high_resolution_clock::now();
|
||||
|
@ -326,15 +325,15 @@ void IHyprLayout::onMouseMove(const Vector2D& mousePos) {
|
|||
|
||||
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();
|
||||
|
||||
if (*PANIMATEMOUSE)
|
||||
if (**PANIMATEMOUSE)
|
||||
DRAGGINGWINDOW->m_vRealPosition = wb.pos();
|
||||
else
|
||||
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) {
|
||||
if (DRAGGINGWINDOW->m_bIsFloating) {
|
||||
|
||||
|
@ -387,7 +386,7 @@ void IHyprLayout::onMouseMove(const Vector2D& mousePos) {
|
|||
CBox wb = {newPos, newSize};
|
||||
wb.round();
|
||||
|
||||
if (*PANIMATE) {
|
||||
if (**PANIMATE) {
|
||||
DRAGGINGWINDOW->m_vRealSize = wb.size();
|
||||
DRAGGINGWINDOW->m_vRealPosition = wb.pos();
|
||||
} else {
|
||||
|
@ -395,14 +394,14 @@ void IHyprLayout::onMouseMove(const Vector2D& mousePos) {
|
|||
DRAGGINGWINDOW->m_vRealPosition.setValueAndWarp(wb.pos());
|
||||
}
|
||||
|
||||
g_pXWaylandManager->setWindowSize(DRAGGINGWINDOW, DRAGGINGWINDOW->m_vRealSize.goalv());
|
||||
g_pXWaylandManager->setWindowSize(DRAGGINGWINDOW, DRAGGINGWINDOW->m_vRealSize.goal());
|
||||
} else {
|
||||
resizeActiveWindow(TICKDELTA, m_eGrabbedCorner, DRAGGINGWINDOW);
|
||||
}
|
||||
}
|
||||
|
||||
// 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
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromVector(middle);
|
||||
|
@ -436,18 +435,18 @@ void IHyprLayout::changeWindowFloatingMode(CWindow* pWindow) {
|
|||
EMIT_HOOK_EVENT("changeFloatingMode", pWindow);
|
||||
|
||||
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->moveToWorkspace(PNEWMON->specialWorkspaceID != 0 ? PNEWMON->specialWorkspaceID : PNEWMON->activeWorkspace);
|
||||
pWindow->updateGroupOutputs();
|
||||
|
||||
// save real pos cuz the func applies the default 5,5 mid
|
||||
const auto PSAVEDPOS = pWindow->m_vRealPosition.goalv();
|
||||
const auto PSAVEDSIZE = pWindow->m_vRealSize.goalv();
|
||||
const auto PSAVEDPOS = pWindow->m_vRealPosition.goal();
|
||||
const auto PSAVEDSIZE = pWindow->m_vRealSize.goal();
|
||||
|
||||
// if the window is pseudo, update its size
|
||||
if (!pWindow->m_bDraggingTiled)
|
||||
pWindow->m_vPseudoSize = pWindow->m_vRealSize.goalv();
|
||||
pWindow->m_vPseudoSize = pWindow->m_vRealSize.goal();
|
||||
|
||||
pWindow->m_vLastFloatingSize = PSAVEDSIZE;
|
||||
|
||||
|
@ -469,16 +468,19 @@ void IHyprLayout::changeWindowFloatingMode(CWindow* pWindow) {
|
|||
|
||||
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)) {
|
||||
pWindow->m_vRealPosition = pWindow->m_vRealPosition.goalv() + (pWindow->m_vRealSize.goalv() - pWindow->m_vLastFloatingSize) / 2.f + Vector2D{10, 10};
|
||||
pWindow->m_vRealSize = pWindow->m_vLastFloatingSize - Vector2D{20, 20};
|
||||
CBox wb = {pWindow->m_vRealPosition.goal() + (pWindow->m_vRealSize.goal() - pWindow->m_vLastFloatingSize) / 2.f, pWindow->m_vLastFloatingSize};
|
||||
wb.round();
|
||||
|
||||
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_vRealSize = pWindow->m_vLastFloatingSize;
|
||||
pWindow->m_vRealPosition = wb.pos();
|
||||
pWindow->m_vRealSize = wb.size();
|
||||
|
||||
pWindow->m_vSize = pWindow->m_vRealSize.goalv();
|
||||
pWindow->m_vPosition = pWindow->m_vRealPosition.goalv();
|
||||
pWindow->m_vSize = wb.pos();
|
||||
pWindow->m_vPosition = wb.size();
|
||||
|
||||
g_pHyprRenderer->damageMonitor(g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID));
|
||||
|
||||
|
@ -504,7 +506,7 @@ void IHyprLayout::moveActiveWindow(const Vector2D& delta, CWindow* pWindow) {
|
|||
return;
|
||||
}
|
||||
|
||||
PWINDOW->m_vRealPosition = PWINDOW->m_vRealPosition.goalv() + delta;
|
||||
PWINDOW->m_vRealPosition = PWINDOW->m_vRealPosition.goal() + delta;
|
||||
|
||||
g_pHyprRenderer->damageWindow(PWINDOW);
|
||||
}
|
||||
|
@ -529,7 +531,7 @@ CWindow* IHyprLayout::getNextWindowCandidate(CWindow* pWindow) {
|
|||
// find whether there is a floating window below this one
|
||||
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 &&
|
||||
!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,
|
||||
w->m_vPosition.y + w->m_vSize.y)) {
|
||||
return w.get();
|
||||
|
@ -542,13 +544,14 @@ CWindow* IHyprLayout::getNextWindowCandidate(CWindow* pWindow) {
|
|||
return m_pLastTiledWindow;
|
||||
|
||||
// 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;
|
||||
|
||||
// if not, floating window
|
||||
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 &&
|
||||
!w->m_bNoFocus && w.get() != pWindow)
|
||||
!w->m_sAdditionalConfigData.noFocus && w.get() != pWindow)
|
||||
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.
|
||||
auto pWindowCandidate = g_pCompositor->vectorToWindowIdeal(pWindow->middle());
|
||||
auto pWindowCandidate = g_pCompositor->vectorToWindowUnified(pWindow->middle(), RESERVED_EXTENTS | INPUT_EXTENTS | ALLOW_FLOATING);
|
||||
|
||||
if (!pWindowCandidate)
|
||||
pWindowCandidate = g_pCompositor->getTopLeftWindowOnWorkspace(pWindow->m_iWorkspaceID);
|
||||
|
@ -591,4 +594,8 @@ void IHyprLayout::requestFocusForWindow(CWindow* pWindow) {
|
|||
g_pCompositor->focusWindow(pWindow);
|
||||
}
|
||||
|
||||
Vector2D IHyprLayout::predictSizeForNewWindow() {
|
||||
return Vector2D{};
|
||||
}
|
||||
|
||||
IHyprLayout::~IHyprLayout() {}
|
||||
|
|
|
@ -181,6 +181,12 @@ class IHyprLayout {
|
|||
*/
|
||||
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:
|
||||
Vector2D m_vBeginDragXY;
|
||||
Vector2D m_vLastDragXY;
|
||||
|
|