mirror of
https://github.com/hyprwm/Hyprland.git
synced 2025-08-02 05:01:56 -07:00
Compare commits
165 Commits
v0.4.0beta
...
v0.6.1beta
Author | SHA1 | Date | |
---|---|---|---|
|
0b525cdc63 | ||
|
6a47a305f8 | ||
|
1a0b2c4ade | ||
|
f1a5cb4979 | ||
|
f5c2dfc706 | ||
|
4d09101e23 | ||
|
314e1f8fbe | ||
|
78bf88ba60 | ||
|
29aab21033 | ||
|
adead82778 | ||
|
45898a57c8 | ||
|
2c8cf6afc4 | ||
|
316b49eee2 | ||
|
8de8f6667e | ||
|
648b2c892c | ||
|
2955698f28 | ||
|
747ff3369d | ||
|
b46f45befa | ||
|
3842b1641f | ||
|
72c86b99eb | ||
|
eb13be1240 | ||
|
45a44f9690 | ||
|
e95e01416e | ||
|
94e8234ac9 | ||
|
c78b811b49 | ||
|
3053f99db6 | ||
|
e7467c60f9 | ||
|
3e8842e1f8 | ||
|
81e36298bf | ||
|
218675246f | ||
|
e4e323a0df | ||
|
f76b9c4852 | ||
|
ae60075226 | ||
|
b25bafda08 | ||
|
a8e2595534 | ||
|
3c6526dbbe | ||
|
4945c5887d | ||
|
ccdb03391e | ||
|
6ba5edd13e | ||
|
31dc70a41a | ||
|
f9745b0d3b | ||
|
64f6818a13 | ||
|
2631489a18 | ||
|
5614f28dfd | ||
|
a98c07cd00 | ||
|
11a5e6bcbf | ||
|
6eefd294af | ||
|
606f4b0794 | ||
|
ff6e3a4d24 | ||
|
c21b062fe5 | ||
|
19d94b87ab | ||
|
bd41776a5a | ||
|
c2ff3d9e76 | ||
|
dbd060247e | ||
|
0ec903808b | ||
|
770bada5d5 | ||
|
499d2e41bf | ||
|
d614fa895e | ||
|
b9f542a60f | ||
|
4c2459861b | ||
|
0f1ad16aec | ||
|
5541098f20 | ||
|
48e33023af | ||
|
0b6c04355a | ||
|
33abb6a5bf | ||
|
1810725a0c | ||
|
84d6e640ff | ||
|
20ad9d3e7d | ||
|
4a3f9ccba2 | ||
|
ff49f22440 | ||
|
a2fa1bc80d | ||
|
593f24a2ec | ||
|
8bd7234d72 | ||
|
f58bb0187b | ||
|
3dc2277fd0 | ||
|
ee7900f819 | ||
|
f7e9a27c0a | ||
|
f5f531562b | ||
|
4efd913de8 | ||
|
bd95301188 | ||
|
d6b324306b | ||
|
dc84935059 | ||
|
95e083dbd3 | ||
|
39d03fc196 | ||
|
5058a74453 | ||
|
ae1bcc909d | ||
|
7c3626f15e | ||
|
f7bdc2e870 | ||
|
faa1b5a44f | ||
|
f428604b6f | ||
|
2feca08a67 | ||
|
837d4af8f6 | ||
|
9c6c5481bb | ||
|
75918c14d7 | ||
|
d179501c4f | ||
|
8e203b0da3 | ||
|
09cd8c45a6 | ||
|
43065657c9 | ||
|
89454ada6c | ||
|
c169f94895 | ||
|
b3ef1fcc54 | ||
|
fd0112425f | ||
|
b69375a918 | ||
|
354e265128 | ||
|
5fa61e5a54 | ||
|
1926bb4659 | ||
|
36ea12b315 | ||
|
0c5d2f04b4 | ||
|
fa6530c7e8 | ||
|
e97b83167f | ||
|
9aec355727 | ||
|
a4e21a25f4 | ||
|
f13217f698 | ||
|
85d2c1d5a6 | ||
|
2208be5175 | ||
|
46d11f7646 | ||
|
16d1b44ef9 | ||
|
e69f2ab4c3 | ||
|
95a626f72e | ||
|
70eb5053fb | ||
|
48ab282a69 | ||
|
018b0684dd | ||
|
94528bcdbc | ||
|
4fa69497ca | ||
|
dc5cc15474 | ||
|
3a2ac11e3e | ||
|
90a859af27 | ||
|
c6953329d5 | ||
|
c451e13e4f | ||
|
d68e09a707 | ||
|
b4de91111a | ||
|
750961e9c1 | ||
|
b5a446ddfd | ||
|
fbc7853459 | ||
|
53146ccf69 | ||
|
506977c13d | ||
|
09b130374d | ||
|
b53c093b88 | ||
|
8929172bc2 | ||
|
6317f64ba0 | ||
|
824d8b954d | ||
|
49fc1ccdb4 | ||
|
c218ed4432 | ||
|
f97b90859a | ||
|
1841d244f0 | ||
|
47404534d0 | ||
|
b7e21d0fa9 | ||
|
90024e534d | ||
|
248ce66459 | ||
|
638b44cabd | ||
|
8f0b963729 | ||
|
7b73570f11 | ||
|
a0f3fc794e | ||
|
263664c58a | ||
|
da80eb8e57 | ||
|
0b8fe2a0aa | ||
|
1642b1ff66 | ||
|
7b9583c1f2 | ||
|
cc80b68545 | ||
|
2bddfa81bc | ||
|
85d91c3d3c | ||
|
d80c90233b | ||
|
d0ca043122 | ||
|
92da453d4d | ||
|
433e4a0eef |
1
.github/FUNDING.yml
vendored
Normal file
1
.github/FUNDING.yml
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
ko_fi: vaxry
|
60
.github/workflows/ci.yaml
vendored
60
.github/workflows/ci.yaml
vendored
@@ -13,31 +13,73 @@ jobs:
|
|||||||
sed -i 's/SigLevel = Required DatabaseOptional/SigLevel = Optional TrustAll/' /etc/pacman.conf
|
sed -i 's/SigLevel = Required DatabaseOptional/SigLevel = Optional TrustAll/' /etc/pacman.conf
|
||||||
pacman --noconfirm --noprogressbar -Syyu
|
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
|
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
|
||||||
|
|
||||||
- name: Set up user
|
- name: Set up user
|
||||||
run: |
|
run: |
|
||||||
useradd -m githubuser
|
useradd -m githubuser
|
||||||
echo -e "root ALL=(ALL:ALL) ALL\ngithubuser ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers
|
echo -e "root ALL=(ALL:ALL) ALL\ngithubuser ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers
|
||||||
|
|
||||||
- name: Build wlroots
|
- name: Build wlroots
|
||||||
run: |
|
run: |
|
||||||
su githubuser -c "cd ~ && git clone https://gitlab.freedesktop.org/wlroots/wlroots"
|
su githubuser -c "cd ~ && git clone https://gitlab.freedesktop.org/wlroots/wlroots"
|
||||||
su githubuser -c "cd ~/wlroots && meson build/ --prefix=/usr && ninja -C build/ && sudo ninja -C build/ install && cd .."
|
su githubuser -c "cd ~/wlroots && meson build/ --prefix=/usr && ninja -C build/ && sudo ninja -C build/ install && cd .."
|
||||||
|
|
||||||
- name: Fix permissions for git
|
- name: Fix permissions for git
|
||||||
run: |
|
run: |
|
||||||
git config --global --add safe.directory /__w/Hyprland/Hyprland
|
git config --global --add safe.directory /__w/Hyprland/Hyprland
|
||||||
|
|
||||||
- name: Checkout Hyprland
|
- name: Checkout Hyprland
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
|
- name: Build Hyprland
|
||||||
- name: Build Hyprland With default settings
|
|
||||||
run: |
|
run: |
|
||||||
git submodule sync --recursive && git submodule update --init --force --recursive
|
git submodule sync --recursive && git submodule update --init --force --recursive
|
||||||
make all
|
make all
|
||||||
|
- name: Compress and package artifacts
|
||||||
- name: Build Hyprland with LEGACY_RENDERER
|
|
||||||
run: |
|
run: |
|
||||||
make legacyrenderer
|
mkdir x86_64-pc-linux-gnu
|
||||||
|
mkdir hyprland
|
||||||
|
mkdir hyprland/example
|
||||||
|
mkdir hyprland/assets
|
||||||
|
cp ./LICENSE hyprland/
|
||||||
|
cp build/Hyprland hyprland/
|
||||||
|
cp hyprctl/hyprctl hyprland/
|
||||||
|
cp subprojects/wlroots/build/libwlroots.so.11032 hyprland/
|
||||||
|
cp build/Hyprland hyprland/
|
||||||
|
cp -r example/ hyprland/
|
||||||
|
cp -r assets/ hyprland/
|
||||||
|
tar -cvf Hyprland.tar.xz hyprland
|
||||||
|
- name: Release
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: Build archive
|
||||||
|
path: Hyprland.tar.xz
|
||||||
|
|
||||||
|
meson:
|
||||||
|
name: "Build Hyprland with Meson (Arch)"
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
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 xcb-util-errors xcb-util-renderutil xcb-util-wm xorg-fonts-encodings xorg-server-common xorg-setxkbmap xorg-xkbcomp xorg-xwayland git go clang lld libc++ pkgconf meson ninja wayland wayland-protocols libinput libxkbcommon pixman glm libdrm libglvnd cairo pango systemd scdoc base-devel seatd
|
||||||
|
- name: Checkout Hyprland
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
submodules: true
|
||||||
|
- name: Configure
|
||||||
|
run: |
|
||||||
|
meson obj-x86_64-pc-linux-gnu \
|
||||||
|
-Ddefault_library=static
|
||||||
|
- name: Compile
|
||||||
|
run: ninja -C obj-x86_64-pc-linux-gnu
|
||||||
|
# - name: Compress artifacts
|
||||||
|
# run: |
|
||||||
|
# mkdir x86_64-pc-linux-gnu
|
||||||
|
# DESTDIR=$PWD/x86_64-pc-linux-gnu meson install -C obj-x86_64-pc-linux-gnu --tags runtime
|
||||||
|
# tar -cvf x86_64-pc-linux-gnu.tar.xz x86_64-pc-linux-gnu
|
||||||
|
# - name: Upload artifacts
|
||||||
|
# uses: actions/upload-artifact@v3
|
||||||
|
# with:
|
||||||
|
# name: Build artifacts (x86_64-pc-linux-gnu)
|
||||||
|
# path: x86_64-pc-linux-gnu.tar.xz
|
||||||
|
26
.github/workflows/nix-meson-ver-update.yaml
vendored
Normal file
26
.github/workflows/nix-meson-ver-update.yaml
vendored
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
name: "Nix & Meson: update version"
|
||||||
|
|
||||||
|
on: [workflow_dispatch]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
update:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Clone repository
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
- name: Update flake and meson version
|
||||||
|
run: |
|
||||||
|
REGEX="([0-9]+(\.[0-9a-zA-Z]+)+)"
|
||||||
|
|
||||||
|
CRT_REV=$(git show-ref --tags --head --abbrev | head -n 1 | head -c 7)
|
||||||
|
TAG_REV=$(git show-ref --tags --abbrev | tail -n 1 | head -c 7)
|
||||||
|
CRT_VER=$(sed -nEe "/$REGEX/{p;q;}" meson.build | awk -F\' '{print $2}')
|
||||||
|
VERSION=$(git show-ref --tags --abbrev | tail -n 1 | tail -c +20)
|
||||||
|
|
||||||
|
if [[ $TAG_REV = $CRT_REV ]] || [[ $CRT_VER != $VERSION ]]; then
|
||||||
|
sed -Ei "s/$REGEX/$VERSION/g" meson.build
|
||||||
|
sed -Ei "s/$REGEX/$VERSION/g" flake.nix
|
||||||
|
fi
|
||||||
|
- uses: stefanzweifel/git-auto-commit-action@v4
|
||||||
|
with:
|
||||||
|
commit_message: "[gha] bump flake and meson version"
|
4
.gitmodules
vendored
4
.gitmodules
vendored
@@ -1,3 +1,3 @@
|
|||||||
[submodule "wlroots"]
|
[submodule "wlroots"]
|
||||||
path = wlroots
|
path = subprojects/wlroots
|
||||||
url = https://gitlab.freedesktop.org/wlroots/wlroots
|
url = https://gitlab.freedesktop.org/wlroots/wlroots.git
|
||||||
|
@@ -35,7 +35,7 @@ execute_process(
|
|||||||
#
|
#
|
||||||
#
|
#
|
||||||
|
|
||||||
include_directories(.)
|
include_directories(. PRIVATE "subprojects/wlroots/include/")
|
||||||
add_compile_options(-std=c++20 -DWLR_USE_UNSTABLE )
|
add_compile_options(-std=c++20 -DWLR_USE_UNSTABLE )
|
||||||
add_compile_options(-Wall -Wextra -Wno-unused-parameter -Wno-unused-value -Wno-missing-field-initializers -Wno-narrowing)
|
add_compile_options(-Wall -Wextra -Wno-unused-parameter -Wno-unused-value -Wno-missing-field-initializers -Wno-narrowing)
|
||||||
find_package(Threads REQUIRED)
|
find_package(Threads REQUIRED)
|
||||||
@@ -59,6 +59,7 @@ ENDIF(NO_XWAYLAND MATCHES true)
|
|||||||
|
|
||||||
IF(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG)
|
IF(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG)
|
||||||
message(STATUS "Configuring Hyprland in Debug with CMake!")
|
message(STATUS "Configuring Hyprland in Debug with CMake!")
|
||||||
|
add_definitions( -DHYPRLAND_DEBUG )
|
||||||
ELSE()
|
ELSE()
|
||||||
# add_compile_options(-O3) # may crash for some
|
# add_compile_options(-O3) # may crash for some
|
||||||
message(STATUS "Configuring Hyprland in Release with CMake!")
|
message(STATUS "Configuring Hyprland in Release with CMake!")
|
||||||
|
22
Makefile
22
Makefile
@@ -59,6 +59,16 @@ pointer-constraints-unstable-v1-protocol.c:
|
|||||||
|
|
||||||
pointer-constraints-unstable-v1-protocol.o: pointer-constraints-unstable-v1-protocol.h
|
pointer-constraints-unstable-v1-protocol.o: pointer-constraints-unstable-v1-protocol.h
|
||||||
|
|
||||||
|
tablet-unstable-v2-protocol.h:
|
||||||
|
$(WAYLAND_SCANNER) server-header \
|
||||||
|
protocols/tablet-unstable-v2.xml $@
|
||||||
|
|
||||||
|
tablet-unstable-v2-protocol.c:
|
||||||
|
$(WAYLAND_SCANNER) private-code \
|
||||||
|
protocols/tablet-unstable-v2.xml $@
|
||||||
|
|
||||||
|
tablet-unstable-v2-protocol.o: tablet-unstable-v2-protocol.h
|
||||||
|
|
||||||
idle-protocol.h:
|
idle-protocol.h:
|
||||||
$(WAYLAND_SCANNER) server-header \
|
$(WAYLAND_SCANNER) server-header \
|
||||||
protocols/idle.xml $@
|
protocols/idle.xml $@
|
||||||
@@ -114,16 +124,16 @@ uninstall:
|
|||||||
rm -f ${PREFIX}/bin/hyprctl
|
rm -f ${PREFIX}/bin/hyprctl
|
||||||
rm -rf ${PREFIX}/share/hyprland
|
rm -rf ${PREFIX}/share/hyprland
|
||||||
|
|
||||||
protocols: xdg-shell-protocol.o wlr-layer-shell-unstable-v1-protocol.o wlr-screencopy-unstable-v1-protocol.o idle-protocol.o ext-workspace-unstable-v1-protocol.o pointer-constraints-unstable-v1-protocol.o
|
protocols: xdg-shell-protocol.o wlr-layer-shell-unstable-v1-protocol.o wlr-screencopy-unstable-v1-protocol.o idle-protocol.o ext-workspace-unstable-v1-protocol.o pointer-constraints-unstable-v1-protocol.o tablet-unstable-v2-protocol.o
|
||||||
|
|
||||||
config:
|
config:
|
||||||
make protocols
|
make protocols
|
||||||
|
|
||||||
sed -i -E 's/(soversion = 11)([^032]|$$)/soversion = 11032/g' ./wlroots/meson.build
|
sed -i -E 's/(soversion = 11)([^032]|$$)/soversion = 11032/g' subprojects/wlroots/meson.build
|
||||||
|
|
||||||
rm -rf ./wlroots/build
|
rm -rf ./subprojects/wlroots/build
|
||||||
|
|
||||||
cd wlroots && meson ./build --prefix=/usr --buildtype=release
|
cd subprojects/wlroots && meson ./build --prefix=/usr --buildtype=release
|
||||||
cd wlroots && ninja -C build/
|
cd subprojects/wlroots && ninja -C build/
|
||||||
|
|
||||||
cd wlroots && sudo ninja -C build/ install
|
cd subprojects/wlroots && ninja -C build/ install
|
||||||
|
25
README.md
25
README.md
@@ -1,6 +1,6 @@
|
|||||||
<div align = center>
|
<div align = center>
|
||||||
|
|
||||||
![Banner]
|
<img src="https://raw.githubusercontent.com/vaxerski/Hyprland/main/assets/header.svg" width="1000" height="500" alt="banner">
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
@@ -19,6 +19,7 @@ Hyprland is a dynamic tiling Wayland compositor based on wlroots that doesn't sa
|
|||||||
|
|
||||||
For Hyprland without the `land` part, see [Hypr], the Xorg window manager.
|
For Hyprland without the `land` part, see [Hypr], the Xorg window manager.
|
||||||
|
|
||||||
|
Please note, especially for folks moving from Hypr, that Hyprland and Hypr share a very different feature set and are not 1:1 experiences.
|
||||||
<br>
|
<br>
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
@@ -51,20 +52,23 @@ Try it out and report bugs / suggestions!
|
|||||||
- Easily expandable and readable codebase
|
- Easily expandable and readable codebase
|
||||||
- Config reloaded instantly upon saving
|
- Config reloaded instantly upon saving
|
||||||
- Custom bezier curve based animations
|
- Custom bezier curve based animations
|
||||||
- wlr_ext workspaces protocol support
|
- `wlr_ext` workspaces protocol support
|
||||||
- Dual Kawase blur
|
- Dual Kawase blur
|
||||||
|
- Drop shadows
|
||||||
- Fully dynamic workspaces
|
- Fully dynamic workspaces
|
||||||
- Closely follows wlroots-git
|
- Closely follows `wlroots-git`
|
||||||
- Bundled wlroots
|
- Bundled wlroots
|
||||||
- Window / layer fade in / out
|
- Window/layer fade in/out
|
||||||
- Tiling / floating / fullscreen windows
|
- Tiling/pseudotiling/floating/fullscreen windows
|
||||||
- Special Workspace (Scratchpad)
|
- Switching workspaces between window modes on the fly
|
||||||
- Window / monitor rules
|
- Special workspace (scratchpad)
|
||||||
|
- Window/monitor rules
|
||||||
- Socket-based IPC
|
- Socket-based IPC
|
||||||
- Event System for bash scripts
|
- Event system for bash scripts
|
||||||
- Rounded corners
|
- Rounded corners
|
||||||
- Full Damage tracking
|
- Full damage tracking
|
||||||
- Docks support
|
- Docks support
|
||||||
|
- Drawing tablet support
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
<br>
|
<br>
|
||||||
@@ -127,7 +131,7 @@ Try it out and report bugs / suggestions!
|
|||||||
[Issues]: https://github.com/vaxerski/Hyprland/issues
|
[Issues]: https://github.com/vaxerski/Hyprland/issues
|
||||||
[Todo]: https://github.com/vaxerski/Hyprland/projects?type=beta
|
[Todo]: https://github.com/vaxerski/Hyprland/projects?type=beta
|
||||||
|
|
||||||
[Contribute]: docs/Contribute.md
|
[Contribute]: https://github.com/vaxerski/Hyprland/wiki/Contributing-&-Debugging
|
||||||
[Install]: https://github.com/vaxerski/Hyprland/wiki/Installation
|
[Install]: https://github.com/vaxerski/Hyprland/wiki/Installation
|
||||||
[Quick Start]: https://github.com/vaxerski/Hyprland/wiki/Quick-start
|
[Quick Start]: https://github.com/vaxerski/Hyprland/wiki/Quick-start
|
||||||
[License]: LICENSE
|
[License]: LICENSE
|
||||||
@@ -148,7 +152,6 @@ Try it out and report bugs / suggestions!
|
|||||||
[Preview A]: https://i.imgur.com/NbrTnZH.png
|
[Preview A]: https://i.imgur.com/NbrTnZH.png
|
||||||
[Preview B]: https://i.imgur.com/ZA4Fa8R.png
|
[Preview B]: https://i.imgur.com/ZA4Fa8R.png
|
||||||
[Preview C]: https://i.imgur.com/BpXxM8H.png
|
[Preview C]: https://i.imgur.com/BpXxM8H.png
|
||||||
[Banner]: https://raw.githubusercontent.com/vaxerski/Hyprland/main/assets/hyprland.png
|
|
||||||
|
|
||||||
|
|
||||||
<!----------------------------------{ Badges }--------------------------------->
|
<!----------------------------------{ Badges }--------------------------------->
|
||||||
|
83
assets/header.svg
Normal file
83
assets/header.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 798 KiB |
5
assets/meson.build
Normal file
5
assets/meson.build
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
wallpapers = ['wall_2K.png', 'wall_4K.png', 'wall_8K.png']
|
||||||
|
|
||||||
|
foreach wallpaper : wallpapers
|
||||||
|
install_data(wallpapers, install_dir: join_paths(get_option('datadir'), 'hyprland'), install_tag: 'runtime')
|
||||||
|
endforeach
|
71
aur/PKGBUILD
71
aur/PKGBUILD
@@ -1,71 +0,0 @@
|
|||||||
# Maintainer: ThatOneCalculator <kainoa@t1c.dev>
|
|
||||||
|
|
||||||
_pkgname="hyprland"
|
|
||||||
pkgname="${_pkgname}"
|
|
||||||
pkgver="0.3.0beta"
|
|
||||||
pkgrel=2
|
|
||||||
pkgdesc="Hyprland is a dynamic tiling Wayland compositor based on wlroots that doesn't sacrifice on its looks."
|
|
||||||
arch=(any)
|
|
||||||
url="https://github.com/vaxerski/Hyprland"
|
|
||||||
license=('BSD')
|
|
||||||
depends=(
|
|
||||||
libxcb
|
|
||||||
xcb-proto
|
|
||||||
xcb-util
|
|
||||||
xcb-util-keysyms
|
|
||||||
libxfixes
|
|
||||||
libx11
|
|
||||||
libxcomposite
|
|
||||||
xorg-xinput
|
|
||||||
libxrender
|
|
||||||
pixman
|
|
||||||
wayland-protocols
|
|
||||||
cairo
|
|
||||||
pango
|
|
||||||
polkit
|
|
||||||
glslang
|
|
||||||
libinput
|
|
||||||
libxcb
|
|
||||||
libxkbcommon
|
|
||||||
opengl-driver
|
|
||||||
pixman
|
|
||||||
wayland
|
|
||||||
xcb-util-errors
|
|
||||||
xcb-util-renderutil
|
|
||||||
xcb-util-wm
|
|
||||||
seatd
|
|
||||||
vulkan-icd-loader
|
|
||||||
vulkan-validation-layers
|
|
||||||
xorg-xwayland)
|
|
||||||
makedepends=(
|
|
||||||
git
|
|
||||||
cmake
|
|
||||||
ninja
|
|
||||||
gcc
|
|
||||||
gdb
|
|
||||||
meson
|
|
||||||
vulkan-headers
|
|
||||||
wayland-protocols
|
|
||||||
xorgproto)
|
|
||||||
source=("${pkgname}-${pkgver}.tar.gz::https://github.com/vaxerski/hyprland/archive/v${pkgver}.tar.gz")
|
|
||||||
sha256sums=('46ba9b61570f3385673dfd27a3d1dc5a084236f138bca1c2537335e0cdce9e78')
|
|
||||||
conflicts=("${_pkgname}-git" "${_pkgname}" "${_pkgname}-bin")
|
|
||||||
options=(!makeflags !buildflags)
|
|
||||||
|
|
||||||
build() {
|
|
||||||
cd "$srcdir/Hyprland-$pkgver"
|
|
||||||
git submodule update --init
|
|
||||||
make all
|
|
||||||
}
|
|
||||||
|
|
||||||
package() {
|
|
||||||
cd "$srcdir/Hyprland-$pkgver"
|
|
||||||
mkdir -p "${pkgdir}/usr/share/wayland-sessions"
|
|
||||||
mkdir -p "${pkgdir}/usr/share/hyprland"
|
|
||||||
install -Dm755 build/Hyprland -t "${pkgdir}/usr/bin"
|
|
||||||
install -Dm755 hyprctl/hyprctl -t "${pkgdir}/usr/bin"
|
|
||||||
install -Dm644 assets/*.png -t "${pkgdir}/usr/share/hyprland"
|
|
||||||
install -Dm644 example/hyprland.desktop -t "${pkgdir}/usr/share/wayland-sessions"
|
|
||||||
install -Dm644 example/hyprland.conf -t "${pkgdir}/usr/share/hyprland"
|
|
||||||
install -Dm644 LICENSE -t "${pkgdir}/usr/share/licenses/${_pkgname}"
|
|
||||||
}
|
|
@@ -1,55 +0,0 @@
|
|||||||
# Maintainer: ThatOneCalculator <kainoa@t1c.dev>
|
|
||||||
|
|
||||||
_pkgname="hyprland"
|
|
||||||
pkgname="${_pkgname}-bin"
|
|
||||||
pkgver="0.3.0beta"
|
|
||||||
pkgrel=2
|
|
||||||
pkgdesc="Hyprland is a dynamic tiling Wayland compositor based on wlroots that doesn't sacrifice on its looks."
|
|
||||||
arch=(any)
|
|
||||||
url="https://github.com/vaxerski/Hyprland"
|
|
||||||
license=('BSD')
|
|
||||||
depends=(
|
|
||||||
libxcb
|
|
||||||
xcb-proto
|
|
||||||
xcb-util
|
|
||||||
xcb-util-keysyms
|
|
||||||
libxfixes
|
|
||||||
libx11
|
|
||||||
libxcomposite
|
|
||||||
xorg-xinput
|
|
||||||
libxrender
|
|
||||||
pixman
|
|
||||||
wayland-protocols
|
|
||||||
cairo
|
|
||||||
pango
|
|
||||||
polkit
|
|
||||||
glslang
|
|
||||||
libinput
|
|
||||||
libxcb
|
|
||||||
libxkbcommon
|
|
||||||
opengl-driver
|
|
||||||
pixman
|
|
||||||
wayland
|
|
||||||
xcb-util-errors
|
|
||||||
xcb-util-renderutil
|
|
||||||
xcb-util-wm
|
|
||||||
seatd
|
|
||||||
vulkan-icd-loader
|
|
||||||
vulkan-validation-layers
|
|
||||||
xorg-xwayland)
|
|
||||||
source=("${pkgname}-${pkgver}.tar.gz::https://github.com/vaxerski/Hyprland/releases/download/v${pkgver}/v${pkgver}.tar.gz")
|
|
||||||
sha256sums=('46ba9b61570f3385673dfd27a3d1dc5a084236f138bca1c2537335e0cdce9e78')
|
|
||||||
conflicts=("${_pkgname}-git" "${_pkgname}" "${_pkgname}-bin")
|
|
||||||
|
|
||||||
package() {
|
|
||||||
cd "$srcdir/Hyprland-$pkgver"
|
|
||||||
mkdir -p "${pkgdir}/usr/share/wayland-sessions"
|
|
||||||
mkdir -p "${pkgdir}/usr/share/hyprland"
|
|
||||||
install -Dm755 ./Hyprland -t "${pkgdir}/usr/bin"
|
|
||||||
install -Dm755 ./hyprctl -t "${pkgdir}/usr/bin"
|
|
||||||
install -Dm755 ./libwlroots.so.11032 -t "${pkgdir}/usr/lib"
|
|
||||||
install -Dm644 assets/*.png -t "${pkgdir}/usr/share/hyprland"
|
|
||||||
install -Dm644 example/hyprland.desktop -t "${pkgdir}/usr/share/wayland-sessions"
|
|
||||||
install -Dm644 example/hyprland.conf -t "${pkgdir}/usr/share/hyprland"
|
|
||||||
install -Dm644 LICENSE -t "${pkgdir}/usr/share/licenses/${_pkgname}"
|
|
||||||
}
|
|
@@ -1,79 +0,0 @@
|
|||||||
# Maintainer: ThatOneCalculator <kainoa@t1c.dev>, Sander van Kasteel <info@sandervankasteel.nl>
|
|
||||||
|
|
||||||
_pkgname="hyprland"
|
|
||||||
pkgname="${_pkgname}-git"
|
|
||||||
pkgver=r655.gef85544
|
|
||||||
pkgrel=1
|
|
||||||
pkgdesc="Hyprland is a dynamic tiling Wayland compositor based on wlroots that doesn't sacrifice on its looks."
|
|
||||||
arch=(any)
|
|
||||||
url="https://github.com/vaxerski/Hyprland"
|
|
||||||
license=('BSD')
|
|
||||||
depends=(
|
|
||||||
libxcb
|
|
||||||
xcb-proto
|
|
||||||
xcb-util
|
|
||||||
xcb-util-keysyms
|
|
||||||
libxfixes
|
|
||||||
libx11
|
|
||||||
libxcomposite
|
|
||||||
xorg-xinput
|
|
||||||
libxrender
|
|
||||||
pixman
|
|
||||||
wayland-protocols
|
|
||||||
cairo
|
|
||||||
pango
|
|
||||||
polkit
|
|
||||||
glslang
|
|
||||||
libinput
|
|
||||||
libxcb
|
|
||||||
libxkbcommon
|
|
||||||
opengl-driver
|
|
||||||
pixman
|
|
||||||
wayland
|
|
||||||
xcb-util-errors
|
|
||||||
xcb-util-renderutil
|
|
||||||
xcb-util-wm
|
|
||||||
seatd
|
|
||||||
vulkan-icd-loader
|
|
||||||
vulkan-validation-layers
|
|
||||||
xorg-xwayland)
|
|
||||||
makedepends=(
|
|
||||||
git
|
|
||||||
cmake
|
|
||||||
ninja
|
|
||||||
gcc
|
|
||||||
gdb
|
|
||||||
meson
|
|
||||||
vulkan-headers
|
|
||||||
wayland-protocols
|
|
||||||
xorgproto)
|
|
||||||
source=("${_pkgname}::git+https://github.com/vaxerski/Hyprland.git")
|
|
||||||
conflicts=("${_pkgname}-git" "${_pkgname}" "${_pkgname}-bin")
|
|
||||||
sha256sums=('SKIP')
|
|
||||||
options=(!makeflags !buildflags)
|
|
||||||
|
|
||||||
pkgver() {
|
|
||||||
cd "$_pkgname"
|
|
||||||
( set -o pipefail
|
|
||||||
git describe --long 2>/dev/null | sed 's/\([^-]*-g\)/r\1/;s/-/./g' ||
|
|
||||||
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
build() {
|
|
||||||
cd "${srcdir}/${_pkgname}"
|
|
||||||
git submodule update --init
|
|
||||||
make all
|
|
||||||
}
|
|
||||||
|
|
||||||
package() {
|
|
||||||
cd "${srcdir}/${_pkgname}"
|
|
||||||
mkdir -p "${pkgdir}/usr/share/wayland-sessions"
|
|
||||||
mkdir -p "${pkgdir}/usr/share/hyprland"
|
|
||||||
install -Dm755 build/Hyprland -t "${pkgdir}/usr/bin"
|
|
||||||
install -Dm755 hyprctl/hyprctl -t "${pkgdir}/usr/bin"
|
|
||||||
install -Dm644 assets/*.png -t "${pkgdir}/usr/share/hyprland"
|
|
||||||
install -Dm644 example/hyprland.desktop -t "${pkgdir}/usr/share/wayland-sessions"
|
|
||||||
install -Dm644 example/hyprland.conf -t "${pkgdir}/usr/share/hyprland"
|
|
||||||
install -Dm644 LICENSE -t "${pkgdir}/usr/share/licenses/${_pkgname}"
|
|
||||||
}
|
|
@@ -27,6 +27,8 @@ If your bug crashes Hyprland, append additionally:
|
|||||||
- The Hyprland log
|
- The Hyprland log
|
||||||
- Coredump / Coredump analysis (with a stacktrace)
|
- Coredump / Coredump analysis (with a stacktrace)
|
||||||
|
|
||||||
|
**Important**: Please do NOT use any package for reporting bugs! Clone and compile from source.
|
||||||
|
|
||||||
## Obtaining the Hyprland log
|
## Obtaining the Hyprland log
|
||||||
If you are in a TTY, and the hyprland session that crashed was the last one you launched, the log will be printed with
|
If you are in a TTY, and the hyprland session that crashed was the last one you launched, the log will be printed with
|
||||||
```
|
```
|
||||||
|
@@ -17,8 +17,7 @@ input {
|
|||||||
}
|
}
|
||||||
|
|
||||||
general {
|
general {
|
||||||
max_fps=60 # deprecated, unused
|
sensitivity=1.0 # for mouse cursor
|
||||||
sensitivity=0.25
|
|
||||||
main_mod=SUPER
|
main_mod=SUPER
|
||||||
|
|
||||||
gaps_in=5
|
gaps_in=5
|
||||||
@@ -27,6 +26,8 @@ general {
|
|||||||
col.active_border=0x66ee1111
|
col.active_border=0x66ee1111
|
||||||
col.inactive_border=0x66333333
|
col.inactive_border=0x66333333
|
||||||
|
|
||||||
|
apply_sens_to_raw=0 # whether to apply the sensitivity to raw input (e.g. used by games where you aim using your mouse)
|
||||||
|
|
||||||
damage_tracking=full # leave it on full unless you hate your GPU and want to make it suffer
|
damage_tracking=full # leave it on full unless you hate your GPU and want to make it suffer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
2
example/meson.build
Normal file
2
example/meson.build
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
install_data('hyprland.conf', install_dir: join_paths(get_option('datadir'), 'hyprland'), install_tag: 'runtime')
|
||||||
|
install_data('hyprland.desktop', install_dir: join_paths(get_option('datadir'), 'wayland-sessions'), install_tag: 'runtime')
|
12
flake.lock
generated
12
flake.lock
generated
@@ -2,11 +2,11 @@
|
|||||||
"nodes": {
|
"nodes": {
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1653931853,
|
"lastModified": 1655807518,
|
||||||
"narHash": "sha256-O3wncIouj9x7gBPntzHeK/Hkmm9M1SGlYq7JI7saTAE=",
|
"narHash": "sha256-5YV29Ry/DpAJc/0Hc/+ISVBAjwHpJvAkeKkcUG5lWsc=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "f1c167688a6f81f4a51ab542e5f476c8c595e457",
|
"rev": "a72d7811be1162dd6804c4e36e5402d76fb6e921",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -26,11 +26,11 @@
|
|||||||
"flake": false,
|
"flake": false,
|
||||||
"locked": {
|
"locked": {
|
||||||
"host": "gitlab.freedesktop.org",
|
"host": "gitlab.freedesktop.org",
|
||||||
"lastModified": 1653658290,
|
"lastModified": 1654618691,
|
||||||
"narHash": "sha256-zZaona39DOZNL93A1KG3zAi8vDttJBirxacq24hWCn4=",
|
"narHash": "sha256-8y3u8CoigjoZOVbA2wCWBHlDNEakv0AVxU46/cOC00s=",
|
||||||
"owner": "wlroots",
|
"owner": "wlroots",
|
||||||
"repo": "wlroots",
|
"repo": "wlroots",
|
||||||
"rev": "75d31509db8c28e8379fe9570118ef8c82284581",
|
"rev": "b89ed9015c3fbe8d339e9d65cf70fdca6e5645bc",
|
||||||
"type": "gitlab"
|
"type": "gitlab"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
35
flake.nix
35
flake.nix
@@ -16,40 +16,37 @@
|
|||||||
}: let
|
}: let
|
||||||
inherit (nixpkgs) lib;
|
inherit (nixpkgs) lib;
|
||||||
genSystems = lib.genAttrs [
|
genSystems = lib.genAttrs [
|
||||||
|
# Add more systems if they are supported
|
||||||
"x86_64-linux"
|
"x86_64-linux"
|
||||||
];
|
];
|
||||||
pkgsFor = nixpkgs.legacyPackages;
|
pkgsFor = nixpkgs.legacyPackages;
|
||||||
# https://github.com/NixOS/rfcs/pull/107
|
mkDate = longDate: (lib.concatStringsSep "-" [
|
||||||
mkVersion = longDate:
|
|
||||||
lib.concatStrings [
|
|
||||||
"0.pre"
|
|
||||||
"+date="
|
|
||||||
(lib.concatStringsSep "-" [
|
|
||||||
(__substring 0 4 longDate)
|
(__substring 0 4 longDate)
|
||||||
(__substring 4 2 longDate)
|
(__substring 4 2 longDate)
|
||||||
(__substring 6 2 longDate)
|
(__substring 6 2 longDate)
|
||||||
])
|
]);
|
||||||
];
|
|
||||||
in {
|
in {
|
||||||
packages = genSystems (system: {
|
overlays.default = _: prev: rec {
|
||||||
wlroots = pkgsFor.${system}.wlroots.overrideAttrs (prev: {
|
wlroots-hyprland = prev.wlroots.overrideAttrs (__: {
|
||||||
version = mkVersion (toString (inputs.wlroots.lastModifiedDate or inputs.wlroots.lastModified or "19700101"));
|
version = mkDate (inputs.wlroots.lastModifiedDate or "19700101");
|
||||||
src = inputs.wlroots;
|
src = inputs.wlroots;
|
||||||
});
|
});
|
||||||
default = pkgsFor.${system}.callPackage ./nix/default.nix {
|
hyprland = prev.callPackage ./nix/default.nix {
|
||||||
version = mkVersion (toString (self.lastModifiedDate or self.lastModified or "19700101"));
|
version = "0.6.0beta" + "+date=" + (mkDate (self.lastModifiedDate or "19700101"));
|
||||||
inherit (self.packages.${system}) wlroots;
|
wlroots = wlroots-hyprland;
|
||||||
};
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
packages = genSystems (system:
|
||||||
|
(self.overlays.default null pkgsFor.${system})
|
||||||
|
// {
|
||||||
|
default = self.packages.${system}.hyprland;
|
||||||
});
|
});
|
||||||
|
|
||||||
formatter = genSystems (system: pkgsFor.${system}.alejandra);
|
formatter = genSystems (system: pkgsFor.${system}.alejandra);
|
||||||
|
|
||||||
nixosModules.default = import ./nix/module.nix self;
|
nixosModules.default = import ./nix/module.nix self;
|
||||||
|
|
||||||
# Deprecated
|
overlay = throw "Hyprland: .overlay output is deprecated, please use the .overlays.default output";
|
||||||
overlays.default = _: prev: {
|
|
||||||
hyprland = self.packages.${prev.system}.default;
|
|
||||||
};
|
|
||||||
overlay = self.overlays.default;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
clean:
|
|
||||||
rm -rf ./hyprctl ./hyprctl
|
|
||||||
all:
|
all:
|
||||||
g++ -std=c++20 ./main.cpp -o ./hyprctl
|
g++ -std=c++20 ./main.cpp -o ./hyprctl
|
||||||
|
clean:
|
||||||
|
rm ./hyprctl
|
@@ -15,8 +15,7 @@
|
|||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
const std::string USAGE = R"#(
|
const std::string USAGE = R"#(usage: hyprctl [command] [(opt)args]
|
||||||
usage: hyprctl [command] [(opt)args]
|
|
||||||
|
|
||||||
monitors
|
monitors
|
||||||
workspaces
|
workspaces
|
||||||
@@ -27,8 +26,7 @@ usage: hyprctl [command] [(opt)args]
|
|||||||
dispatch
|
dispatch
|
||||||
keyword
|
keyword
|
||||||
version
|
version
|
||||||
reload
|
reload)#";
|
||||||
)#";
|
|
||||||
|
|
||||||
void request(std::string arg) {
|
void request(std::string arg) {
|
||||||
const auto SERVERSOCKET = socket(AF_UNIX, SOCK_STREAM, 0);
|
const auto SERVERSOCKET = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||||
@@ -121,7 +119,7 @@ int main(int argc, char** argv) {
|
|||||||
int bflag = 0, sflag = 0, index, c;
|
int bflag = 0, sflag = 0, index, c;
|
||||||
|
|
||||||
if (argc < 2) {
|
if (argc < 2) {
|
||||||
printf("%s", USAGE.c_str());
|
printf("%s\n", USAGE.c_str());
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -136,10 +134,12 @@ int main(int argc, char** argv) {
|
|||||||
else if (!strcmp(argv[1], "dispatch")) dispatchRequest(argc, argv);
|
else if (!strcmp(argv[1], "dispatch")) dispatchRequest(argc, argv);
|
||||||
else if (!strcmp(argv[1], "keyword")) keywordRequest(argc, argv);
|
else if (!strcmp(argv[1], "keyword")) keywordRequest(argc, argv);
|
||||||
else if (!strcmp(argv[1], "--batch")) batchRequest(argc, argv);
|
else if (!strcmp(argv[1], "--batch")) batchRequest(argc, argv);
|
||||||
|
else if (!strcmp(argv[1], "--help")) printf("%s", USAGE.c_str());
|
||||||
else {
|
else {
|
||||||
printf("%s", USAGE.c_str());
|
printf("%s\n", USAGE.c_str());
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
3
hyprctl/meson.build
Normal file
3
hyprctl/meson.build
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
executable('hyprctl', 'main.cpp',
|
||||||
|
install: true
|
||||||
|
)
|
26
meson.build
Normal file
26
meson.build
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
project('Hyprland', 'cpp', 'c',
|
||||||
|
version : '0.6.0beta',
|
||||||
|
default_options : ['warning_level=3', 'cpp_std=c++20', 'default_library=static'])
|
||||||
|
|
||||||
|
wlroots = subproject('wlroots', default_options: ['examples=false'])
|
||||||
|
have_xwlr = wlroots.get_variable('features').get('xwayland')
|
||||||
|
xcb_dep = dependency('xcb', required: get_option('xwayland'))
|
||||||
|
|
||||||
|
if get_option('xwayland').enabled() and not have_xwlr
|
||||||
|
error('Cannot enable Xwayland in Hyprland: wlroots has been built without Xwayland support')
|
||||||
|
endif
|
||||||
|
have_xwayland = xcb_dep.found() and have_xwlr
|
||||||
|
|
||||||
|
if not have_xwayland
|
||||||
|
add_project_arguments('-DNO_XWAYLAND', language: 'cpp')
|
||||||
|
endif
|
||||||
|
|
||||||
|
if get_option('buildtype') == 'debug'
|
||||||
|
add_project_arguments('-DHYPRLAND_DEBUG', language: 'cpp')
|
||||||
|
endif
|
||||||
|
|
||||||
|
subdir('protocols')
|
||||||
|
subdir('src')
|
||||||
|
subdir('hyprctl')
|
||||||
|
subdir('assets')
|
||||||
|
subdir('example')
|
1
meson_options.txt
Normal file
1
meson_options.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
option('xwayland', type: 'feature', value: 'auto', description: 'Enable support for X11 applications')
|
@@ -3,7 +3,7 @@
|
|||||||
stdenv,
|
stdenv,
|
||||||
fetchFromGitHub,
|
fetchFromGitHub,
|
||||||
pkg-config,
|
pkg-config,
|
||||||
cmake,
|
meson,
|
||||||
ninja,
|
ninja,
|
||||||
libdrm,
|
libdrm,
|
||||||
libinput,
|
libinput,
|
||||||
@@ -27,7 +27,7 @@ stdenv.mkDerivation {
|
|||||||
src = ../.;
|
src = ../.;
|
||||||
|
|
||||||
nativeBuildInputs = [
|
nativeBuildInputs = [
|
||||||
cmake
|
meson
|
||||||
ninja
|
ninja
|
||||||
pkg-config
|
pkg-config
|
||||||
];
|
];
|
||||||
@@ -48,33 +48,14 @@ stdenv.mkDerivation {
|
|||||||
]
|
]
|
||||||
++ lib.optional enableXWayland xwayland;
|
++ lib.optional enableXWayland xwayland;
|
||||||
|
|
||||||
cmakeFlags =
|
mesonBuildType = "release";
|
||||||
["-DCMAKE_BUILD_TYPE=Release"]
|
|
||||||
++ lib.optional (!enableXWayland) "-DNO_XWAYLAND=true";
|
|
||||||
|
|
||||||
# enables building with nix-supplied wlroots instead of submodule
|
mesonFlags = lib.optional (!enableXWayland) "-DNO_XWAYLAND=true";
|
||||||
prePatch = ''
|
|
||||||
sed -Ei 's/"\.\.\/wlroots\/include\/([a-zA-Z0-9./_-]+)"/<\1>/g' src/includes.hpp
|
|
||||||
'';
|
|
||||||
postPatch = ''
|
|
||||||
make protocols
|
|
||||||
'';
|
|
||||||
|
|
||||||
postBuild = ''
|
patches = [
|
||||||
pushd ../hyprctl
|
# make meson use the provided wlroots instead of the git submodule
|
||||||
make all
|
./meson-build.patch
|
||||||
popd
|
];
|
||||||
'';
|
|
||||||
|
|
||||||
installPhase = ''
|
|
||||||
pushd ..
|
|
||||||
install -Dm644 ./example/hyprland.desktop -t $out/share/wayland-sessions
|
|
||||||
install -Dm755 ./build/Hyprland -t $out/bin
|
|
||||||
install -Dm755 ./hyprctl/hyprctl -t $out/bin
|
|
||||||
install -Dm644 ./assets/* -t $out/share/hyprland
|
|
||||||
install -Dm644 ./example/hyprland.conf -t $out/share/hyprland
|
|
||||||
popd
|
|
||||||
'';
|
|
||||||
|
|
||||||
passthru.providedSessions = ["hyprland"];
|
passthru.providedSessions = ["hyprland"];
|
||||||
|
|
||||||
|
36
nix/meson-build.patch
Normal file
36
nix/meson-build.patch
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
diff --git a/meson.build b/meson.build
|
||||||
|
index 22ee4bf..5528613 100644
|
||||||
|
--- a/meson.build
|
||||||
|
+++ b/meson.build
|
||||||
|
@@ -2,16 +2,10 @@ project('Hyprland', 'cpp', 'c',
|
||||||
|
version : '0.1',
|
||||||
|
default_options : ['warning_level=3', 'cpp_std=c++20', 'default_library=static'])
|
||||||
|
|
||||||
|
-wlroots = subproject('wlroots', default_options: ['examples=false'])
|
||||||
|
-have_xwlr = wlroots.get_variable('features').get('xwayland')
|
||||||
|
+wlroots = dependency('wlroots', version: '>=0.16.0')
|
||||||
|
xcb_dep = dependency('xcb', required: get_option('xwayland'))
|
||||||
|
|
||||||
|
-if get_option('xwayland').enabled() and not have_xwlr
|
||||||
|
- error('Cannot enable Xwayland in Hyprland: wlroots has been built without Xwayland support')
|
||||||
|
-endif
|
||||||
|
-have_xwayland = xcb_dep.found() and have_xwlr
|
||||||
|
-
|
||||||
|
-if not have_xwayland
|
||||||
|
+if not xcb_dep.found()
|
||||||
|
add_project_arguments('-DNO_XWAYLAND', language: 'cpp')
|
||||||
|
endif
|
||||||
|
|
||||||
|
diff --git a/src/meson.build b/src/meson.build
|
||||||
|
index 5d64188..a676333 100644
|
||||||
|
--- a/src/meson.build
|
||||||
|
+++ b/src/meson.build
|
||||||
|
@@ -7,7 +7,7 @@ executable('Hyprland', src,
|
||||||
|
server_protos,
|
||||||
|
dependency('wayland-server'),
|
||||||
|
dependency('wayland-client'),
|
||||||
|
- wlroots.get_variable('wlroots'),
|
||||||
|
+ wlroots,
|
||||||
|
dependency('cairo'),
|
||||||
|
dependency('pango'),
|
||||||
|
dependency('pangocairo'),
|
@@ -19,7 +19,7 @@ in {
|
|||||||
|
|
||||||
package = mkOption {
|
package = mkOption {
|
||||||
type = types.package;
|
type = types.package;
|
||||||
default = self.packages.${pkgs.system}.default;
|
default = pkgs.hyprland or self.packages.${pkgs.system}.default;
|
||||||
defaultText = literalExpression "<Hyprland flake>.packages.<system>.default";
|
defaultText = literalExpression "<Hyprland flake>.packages.<system>.default";
|
||||||
example = literalExpression "<Hyprland flake>.packages.<system>.default.override { }";
|
example = literalExpression "<Hyprland flake>.packages.<system>.default.override { }";
|
||||||
description = ''
|
description = ''
|
||||||
|
51
protocols/meson.build
Normal file
51
protocols/meson.build
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
wayland_protos = dependency('wayland-protocols',
|
||||||
|
version: '>=1.25',
|
||||||
|
fallback: 'wayland-protocols',
|
||||||
|
default_options: ['tests=false'],
|
||||||
|
)
|
||||||
|
wl_protocol_dir = wayland_protos.get_variable('pkgdatadir')
|
||||||
|
|
||||||
|
wayland_scanner_dep = dependency('wayland-scanner', native: true)
|
||||||
|
wayland_scanner = find_program(
|
||||||
|
wayland_scanner_dep.get_variable('wayland_scanner'),
|
||||||
|
native: true,
|
||||||
|
)
|
||||||
|
|
||||||
|
protocols = [
|
||||||
|
[wl_protocol_dir, 'stable/xdg-shell/xdg-shell.xml'],
|
||||||
|
['wlr-layer-shell-unstable-v1.xml'],
|
||||||
|
['ext-workspace-unstable-v1.xml'],
|
||||||
|
['pointer-constraints-unstable-v1.xml'],
|
||||||
|
['tablet-unstable-v2.xml'],
|
||||||
|
['idle.xml']
|
||||||
|
]
|
||||||
|
wl_protos_src = []
|
||||||
|
wl_protos_headers = []
|
||||||
|
foreach p : protocols
|
||||||
|
xml = join_paths(p)
|
||||||
|
wl_protos_src += custom_target(
|
||||||
|
xml.underscorify() + '_server_c',
|
||||||
|
input: xml,
|
||||||
|
output: '@BASENAME@-protocol.c',
|
||||||
|
command: [wayland_scanner, 'private-code', '@INPUT@', '@OUTPUT@'],
|
||||||
|
)
|
||||||
|
wl_protos_headers += custom_target(
|
||||||
|
xml.underscorify() + '_server_h',
|
||||||
|
input: xml,
|
||||||
|
output: '@BASENAME@-protocol.h',
|
||||||
|
command: [wayland_scanner, 'server-header', '@INPUT@', '@OUTPUT@'],
|
||||||
|
)
|
||||||
|
endforeach
|
||||||
|
|
||||||
|
wayland_server = dependency('wayland-server', version: '>=1.20.0')
|
||||||
|
|
||||||
|
lib_server_protos = static_library(
|
||||||
|
'server_protos',
|
||||||
|
wl_protos_src + wl_protos_headers,
|
||||||
|
dependencies: wayland_server.partial_dependency(compile_args: true),
|
||||||
|
)
|
||||||
|
|
||||||
|
server_protos = declare_dependency(
|
||||||
|
link_with: lib_server_protos,
|
||||||
|
sources: wl_protos_headers,
|
||||||
|
)
|
1178
protocols/tablet-unstable-v2.xml
Normal file
1178
protocols/tablet-unstable-v2.xml
Normal file
File diff suppressed because it is too large
Load Diff
@@ -7,6 +7,16 @@ CCompositor::CCompositor() {
|
|||||||
|
|
||||||
Debug::log(LOG, "Instance Signature: %s", m_szInstanceSignature.c_str());
|
Debug::log(LOG, "Instance Signature: %s", m_szInstanceSignature.c_str());
|
||||||
|
|
||||||
|
Debug::log(LOG, "===== SYSTEM INFO: =====");
|
||||||
|
|
||||||
|
logSystemInfo();
|
||||||
|
|
||||||
|
Debug::log(LOG, "========================");
|
||||||
|
|
||||||
|
Debug::log(NONE, "\n\n"); // pad
|
||||||
|
|
||||||
|
Debug::log(INFO, "If you are crashing, or encounter any bugs, please consult https://github.com/hyprwm/Hyprland/wiki/Crashing-and-bugs\n\n");
|
||||||
|
|
||||||
setenv("HYPRLAND_INSTANCE_SIGNATURE", m_szInstanceSignature.c_str(), true);
|
setenv("HYPRLAND_INSTANCE_SIGNATURE", m_szInstanceSignature.c_str(), true);
|
||||||
|
|
||||||
const auto INSTANCEPATH = "/tmp/hypr/" + m_szInstanceSignature;
|
const auto INSTANCEPATH = "/tmp/hypr/" + m_szInstanceSignature;
|
||||||
@@ -109,6 +119,8 @@ CCompositor::CCompositor() {
|
|||||||
m_sWLRVirtPtrMgr = wlr_virtual_pointer_manager_v1_create(m_sWLDisplay);
|
m_sWLRVirtPtrMgr = wlr_virtual_pointer_manager_v1_create(m_sWLDisplay);
|
||||||
|
|
||||||
m_sWLRToplevelMgr = wlr_foreign_toplevel_manager_v1_create(m_sWLDisplay);
|
m_sWLRToplevelMgr = wlr_foreign_toplevel_manager_v1_create(m_sWLDisplay);
|
||||||
|
|
||||||
|
m_sWLRTabletManager = wlr_tablet_v2_create(m_sWLDisplay);
|
||||||
}
|
}
|
||||||
|
|
||||||
CCompositor::~CCompositor() {
|
CCompositor::~CCompositor() {
|
||||||
@@ -441,7 +453,11 @@ wlr_surface* CCompositor::vectorWindowToSurface(const Vector2D& pos, CWindow* pW
|
|||||||
|
|
||||||
double subx, suby;
|
double subx, suby;
|
||||||
|
|
||||||
const auto PFOUND = wlr_xdg_surface_surface_at(PSURFACE, pos.x - pWindow->m_vRealPosition.vec().x, pos.y - pWindow->m_vRealPosition.vec().y, &subx, &suby);
|
// calc for oversized windows... fucking bullshit, again.
|
||||||
|
wlr_box geom;
|
||||||
|
wlr_xdg_surface_get_geometry(pWindow->m_uSurface.xdg, &geom);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
if (PFOUND) {
|
if (PFOUND) {
|
||||||
sl.x = subx;
|
sl.x = subx;
|
||||||
@@ -452,6 +468,9 @@ wlr_surface* CCompositor::vectorWindowToSurface(const Vector2D& pos, CWindow* pW
|
|||||||
sl.x = pos.x - pWindow->m_vRealPosition.vec().x;
|
sl.x = pos.x - pWindow->m_vRealPosition.vec().x;
|
||||||
sl.y = pos.y - pWindow->m_vRealPosition.vec().y;
|
sl.y = pos.y - pWindow->m_vRealPosition.vec().y;
|
||||||
|
|
||||||
|
sl.x += geom.x;
|
||||||
|
sl.y += geom.y;
|
||||||
|
|
||||||
return PSURFACE->surface;
|
return PSURFACE->surface;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -583,11 +602,11 @@ CWindow* CCompositor::getWindowForPopup(wlr_xdg_popup* popup) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
wlr_surface* CCompositor::vectorToLayerSurface(const Vector2D& pos, std::list<SLayerSurface*>* layerSurfaces, Vector2D* sCoords) {
|
wlr_surface* CCompositor::vectorToLayerSurface(const Vector2D& pos, std::list<SLayerSurface*>* layerSurfaces, Vector2D* sCoords) {
|
||||||
for (auto& l : *layerSurfaces) {
|
for (auto it = layerSurfaces->rbegin(); it != layerSurfaces->rend(); it++) {
|
||||||
if (l->fadingOut || (l->layerSurface && !l->layerSurface->mapped))
|
if ((*it)->fadingOut || !(*it)->layerSurface || ((*it)->layerSurface && !(*it)->layerSurface->mapped))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const auto SURFACEAT = wlr_layer_surface_v1_surface_at(l->layerSurface, pos.x - l->geometry.x, pos.y - l->geometry.y, &sCoords->x, &sCoords->y);
|
const auto SURFACEAT = wlr_layer_surface_v1_surface_at((*it)->layerSurface, pos.x - (*it)->geometry.x, pos.y - (*it)->geometry.y, &sCoords->x, &sCoords->y);
|
||||||
|
|
||||||
if (SURFACEAT)
|
if (SURFACEAT)
|
||||||
return SURFACEAT;
|
return SURFACEAT;
|
||||||
@@ -761,18 +780,24 @@ void CCompositor::cleanupFadingOut() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
CWindow* CCompositor::getWindowInDirection(CWindow* pWindow, char dir) {
|
CWindow* CCompositor::getWindowInDirection(CWindow* pWindow, char dir) {
|
||||||
const auto POSA = pWindow->m_vPosition;
|
|
||||||
const auto SIZEA = pWindow->m_vSize;
|
const auto WINDOWIDEALBB = pWindow->getWindowIdealBoundingBoxIgnoreReserved();
|
||||||
|
|
||||||
|
const auto POSA = Vector2D(WINDOWIDEALBB.x, WINDOWIDEALBB.y);
|
||||||
|
const auto SIZEA = Vector2D(WINDOWIDEALBB.width, WINDOWIDEALBB.height);
|
||||||
|
|
||||||
auto longestIntersect = -1;
|
auto longestIntersect = -1;
|
||||||
CWindow* longestIntersectWindow = nullptr;
|
CWindow* longestIntersectWindow = nullptr;
|
||||||
|
|
||||||
for (auto& w : m_lWindows) {
|
for (auto& w : m_lWindows) {
|
||||||
if (&w == pWindow || !windowValidMapped(&w) || w.m_bIsFloating || w.m_iWorkspaceID != pWindow->m_iWorkspaceID)
|
if (&w == pWindow || !windowValidMapped(&w) || w.m_bIsFloating || !isWorkspaceVisible(w.m_iWorkspaceID))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const auto POSB = w.m_vPosition;
|
const auto BWINDOWIDEALBB = w.getWindowIdealBoundingBoxIgnoreReserved();
|
||||||
const auto SIZEB = w.m_vSize;
|
|
||||||
|
const auto POSB = Vector2D(BWINDOWIDEALBB.x, BWINDOWIDEALBB.y);
|
||||||
|
const auto SIZEB = Vector2D(BWINDOWIDEALBB.width, BWINDOWIDEALBB.height);
|
||||||
|
|
||||||
switch (dir) {
|
switch (dir) {
|
||||||
case 'l':
|
case 'l':
|
||||||
if (STICKS(POSA.x, POSB.x + SIZEB.x)) {
|
if (STICKS(POSA.x, POSB.x + SIZEB.x)) {
|
||||||
@@ -1091,3 +1116,17 @@ bool CCompositor::workspaceIDOutOfBounds(const int& id) {
|
|||||||
|
|
||||||
return std::clamp(id, lowestID, highestID) != id;
|
return std::clamp(id, lowestID, highestID) != id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CCompositor::setWindowFullscreen(CWindow* pWindow, bool on, eFullscreenMode mode) {
|
||||||
|
if (!windowValidMapped(pWindow))
|
||||||
|
return;
|
||||||
|
|
||||||
|
g_pLayoutManager->getCurrentLayout()->fullscreenRequestForWindow(pWindow, mode, on);
|
||||||
|
|
||||||
|
g_pXWaylandManager->setWindowFullscreen(pWindow, pWindow->m_bIsFullscreen && mode == FULLSCREEN_FULL);
|
||||||
|
// make all windows on the same workspace under the fullscreen window
|
||||||
|
for (auto& w : g_pCompositor->m_lWindows) {
|
||||||
|
if (w.m_iWorkspaceID == pWindow->m_iWorkspaceID)
|
||||||
|
w.m_bCreatedOverFullscreen = false;
|
||||||
|
}
|
||||||
|
}
|
@@ -10,7 +10,7 @@
|
|||||||
#include "config/ConfigManager.hpp"
|
#include "config/ConfigManager.hpp"
|
||||||
#include "managers/ThreadManager.hpp"
|
#include "managers/ThreadManager.hpp"
|
||||||
#include "managers/XWaylandManager.hpp"
|
#include "managers/XWaylandManager.hpp"
|
||||||
#include "managers/InputManager.hpp"
|
#include "managers/input/InputManager.hpp"
|
||||||
#include "managers/LayoutManager.hpp"
|
#include "managers/LayoutManager.hpp"
|
||||||
#include "managers/KeybindManager.hpp"
|
#include "managers/KeybindManager.hpp"
|
||||||
#include "managers/AnimationManager.hpp"
|
#include "managers/AnimationManager.hpp"
|
||||||
@@ -59,6 +59,7 @@ public:
|
|||||||
wlr_xdg_decoration_manager_v1* m_sWLRXDGDecoMgr;
|
wlr_xdg_decoration_manager_v1* m_sWLRXDGDecoMgr;
|
||||||
wlr_virtual_pointer_manager_v1* m_sWLRVirtPtrMgr;
|
wlr_virtual_pointer_manager_v1* m_sWLRVirtPtrMgr;
|
||||||
wlr_foreign_toplevel_manager_v1* m_sWLRToplevelMgr;
|
wlr_foreign_toplevel_manager_v1* m_sWLRToplevelMgr;
|
||||||
|
wlr_tablet_manager_v2* m_sWLRTabletManager;
|
||||||
// ------------------------------------------------- //
|
// ------------------------------------------------- //
|
||||||
|
|
||||||
|
|
||||||
@@ -131,6 +132,7 @@ public:
|
|||||||
int getNextAvailableMonitorID();
|
int getNextAvailableMonitorID();
|
||||||
void moveWorkspaceToMonitor(CWorkspace*, SMonitor*);
|
void moveWorkspaceToMonitor(CWorkspace*, SMonitor*);
|
||||||
bool workspaceIDOutOfBounds(const int&);
|
bool workspaceIDOutOfBounds(const int&);
|
||||||
|
void setWindowFullscreen(CWindow*, bool, eFullscreenMode);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void initAllSignals();
|
void initAllSignals();
|
||||||
|
@@ -1,11 +1,14 @@
|
|||||||
#include "Window.hpp"
|
#include "Window.hpp"
|
||||||
#include "Compositor.hpp"
|
#include "Compositor.hpp"
|
||||||
|
#include "render/decorations/CHyprDropShadowDecoration.hpp"
|
||||||
|
|
||||||
CWindow::CWindow() {
|
CWindow::CWindow() {
|
||||||
m_vRealPosition.create(AVARTYPE_VECTOR, &g_pConfigManager->getConfigValuePtr("animations:windows_speed")->floatValue, &g_pConfigManager->getConfigValuePtr("animations:windows")->intValue, &g_pConfigManager->getConfigValuePtr("animations:windows_curve")->strValue, (void*) this, AVARDAMAGE_ENTIRE);
|
m_vRealPosition.create(AVARTYPE_VECTOR, &g_pConfigManager->getConfigValuePtr("animations:windows_speed")->floatValue, &g_pConfigManager->getConfigValuePtr("animations:windows")->intValue, &g_pConfigManager->getConfigValuePtr("animations:windows_curve")->strValue, (void*) this, AVARDAMAGE_ENTIRE);
|
||||||
m_vRealSize.create(AVARTYPE_VECTOR, &g_pConfigManager->getConfigValuePtr("animations:windows_speed")->floatValue, &g_pConfigManager->getConfigValuePtr("animations:windows")->intValue, &g_pConfigManager->getConfigValuePtr("animations:windows_curve")->strValue, (void*)this, AVARDAMAGE_ENTIRE);
|
m_vRealSize.create(AVARTYPE_VECTOR, &g_pConfigManager->getConfigValuePtr("animations:windows_speed")->floatValue, &g_pConfigManager->getConfigValuePtr("animations:windows")->intValue, &g_pConfigManager->getConfigValuePtr("animations:windows_curve")->strValue, (void*)this, AVARDAMAGE_ENTIRE);
|
||||||
m_cRealBorderColor.create(AVARTYPE_COLOR, &g_pConfigManager->getConfigValuePtr("animations:borders_speed")->floatValue, &g_pConfigManager->getConfigValuePtr("animations:borders")->intValue, &g_pConfigManager->getConfigValuePtr("animations:borders_curve")->strValue, (void*)this, AVARDAMAGE_BORDER);
|
m_cRealBorderColor.create(AVARTYPE_COLOR, &g_pConfigManager->getConfigValuePtr("animations:borders_speed")->floatValue, &g_pConfigManager->getConfigValuePtr("animations:borders")->intValue, &g_pConfigManager->getConfigValuePtr("animations:borders_curve")->strValue, (void*)this, AVARDAMAGE_BORDER);
|
||||||
m_fAlpha.create(AVARTYPE_FLOAT, &g_pConfigManager->getConfigValuePtr("animations:fadein_speed")->floatValue, &g_pConfigManager->getConfigValuePtr("animations:fadein")->intValue, &g_pConfigManager->getConfigValuePtr("animations:fadein_curve")->strValue, (void*)this, AVARDAMAGE_ENTIRE);
|
m_fAlpha.create(AVARTYPE_FLOAT, &g_pConfigManager->getConfigValuePtr("animations:fadein_speed")->floatValue, &g_pConfigManager->getConfigValuePtr("animations:fadein")->intValue, &g_pConfigManager->getConfigValuePtr("animations:fadein_curve")->strValue, (void*)this, AVARDAMAGE_ENTIRE);
|
||||||
|
|
||||||
|
m_dWindowDecorations.emplace_back(std::make_unique<CHyprDropShadowDecoration>(this)); // put the shadow so it's the first deco (has to be rendered first)
|
||||||
}
|
}
|
||||||
|
|
||||||
CWindow::~CWindow() {
|
CWindow::~CWindow() {
|
||||||
@@ -16,8 +19,9 @@ CWindow::~CWindow() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
wlr_box CWindow::getFullWindowBoundingBox() {
|
wlr_box CWindow::getFullWindowBoundingBox() {
|
||||||
|
static auto* const PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue;
|
||||||
|
|
||||||
SWindowDecorationExtents maxExtents;
|
SWindowDecorationExtents maxExtents = {{*PBORDERSIZE + 1, *PBORDERSIZE + 1}, {*PBORDERSIZE + 1, *PBORDERSIZE + 1}};
|
||||||
|
|
||||||
for (auto& wd : m_dWindowDecorations) {
|
for (auto& wd : m_dWindowDecorations) {
|
||||||
|
|
||||||
@@ -44,3 +48,28 @@ wlr_box CWindow::getFullWindowBoundingBox() {
|
|||||||
|
|
||||||
return finalBox;
|
return finalBox;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wlr_box CWindow::getWindowIdealBoundingBoxIgnoreReserved() {
|
||||||
|
|
||||||
|
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
|
||||||
|
|
||||||
|
auto POS = m_vPosition;
|
||||||
|
auto SIZE = m_vSize;
|
||||||
|
|
||||||
|
if (DELTALESSTHAN(POS.y - PMONITOR->vecPosition.y, PMONITOR->vecReservedTopLeft.y, 1)) {
|
||||||
|
POS.y = PMONITOR->vecPosition.y;
|
||||||
|
SIZE.y += PMONITOR->vecReservedTopLeft.y;
|
||||||
|
}
|
||||||
|
if (DELTALESSTHAN(POS.x - PMONITOR->vecPosition.x, PMONITOR->vecReservedTopLeft.x, 1)) {
|
||||||
|
POS.x = PMONITOR->vecPosition.x;
|
||||||
|
SIZE.x += PMONITOR->vecReservedTopLeft.x;
|
||||||
|
}
|
||||||
|
if (DELTALESSTHAN(POS.x + SIZE.x - PMONITOR->vecPosition.x, PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x, 1)) {
|
||||||
|
SIZE.x += PMONITOR->vecReservedBottomRight.x;
|
||||||
|
}
|
||||||
|
if (DELTALESSTHAN(POS.y + SIZE.y - PMONITOR->vecPosition.y, PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y, 1)) {
|
||||||
|
SIZE.y += PMONITOR->vecReservedBottomRight.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
return wlr_box{(int)POS.x, (int)POS.y, (int)SIZE.x, (int)SIZE.y};
|
||||||
|
}
|
@@ -15,6 +15,7 @@ struct SWindowSpecialRenderData {
|
|||||||
struct SWindowAdditionalConfigData {
|
struct SWindowAdditionalConfigData {
|
||||||
std::string animationStyle = "";
|
std::string animationStyle = "";
|
||||||
int rounding = -1; // -1 means no
|
int rounding = -1; // -1 means no
|
||||||
|
bool forceNoBlur = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
class CWindow {
|
class CWindow {
|
||||||
@@ -75,6 +76,7 @@ public:
|
|||||||
|
|
||||||
// For nofocus
|
// For nofocus
|
||||||
bool m_bNoFocus = false;
|
bool m_bNoFocus = false;
|
||||||
|
bool m_bNoInitialFocus = false;
|
||||||
|
|
||||||
SSurfaceTreeNode* m_pSurfaceTree = nullptr;
|
SSurfaceTreeNode* m_pSurfaceTree = nullptr;
|
||||||
|
|
||||||
@@ -108,5 +110,6 @@ public:
|
|||||||
|
|
||||||
// methods
|
// methods
|
||||||
wlr_box getFullWindowBoundingBox();
|
wlr_box getFullWindowBoundingBox();
|
||||||
|
wlr_box getWindowIdealBoundingBoxIgnoreReserved();
|
||||||
|
|
||||||
};
|
};
|
@@ -18,20 +18,22 @@ CConfigManager::CConfigManager() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CConfigManager::setDefaultVars() {
|
void CConfigManager::setDefaultVars() {
|
||||||
configValues["general:max_fps"].intValue = 240;
|
configValues["general:max_fps"].intValue = 60;
|
||||||
configValues["general:sensitivity"].floatValue = 0.25f;
|
configValues["general:sensitivity"].floatValue = 1.0f;
|
||||||
configValues["general:apply_sens_to_raw"].intValue = 1;
|
configValues["general:apply_sens_to_raw"].intValue = 0;
|
||||||
configValues["general:main_mod"].strValue = "SUPER"; // exposed to the user for easier configuring
|
configValues["general:main_mod"].strValue = "SUPER"; // exposed to the user for easier configuring
|
||||||
configValues["general:main_mod_internal"].intValue = g_pKeybindManager->stringToModMask("SUPER"); // actually used and automatically calculated
|
configValues["general:main_mod_internal"].intValue = g_pKeybindManager->stringToModMask("SUPER"); // actually used and automatically calculated
|
||||||
|
|
||||||
configValues["general:damage_tracking"].strValue = "none";
|
configValues["general:damage_tracking"].strValue = "full";
|
||||||
configValues["general:damage_tracking_internal"].intValue = DAMAGE_TRACKING_NONE;
|
configValues["general:damage_tracking_internal"].intValue = DAMAGE_TRACKING_FULL;
|
||||||
|
|
||||||
configValues["general:border_size"].intValue = 1;
|
configValues["general:border_size"].intValue = 1;
|
||||||
|
configValues["general:no_border_on_floating"].intValue = 0;
|
||||||
configValues["general:gaps_in"].intValue = 5;
|
configValues["general:gaps_in"].intValue = 5;
|
||||||
configValues["general:gaps_out"].intValue = 20;
|
configValues["general:gaps_out"].intValue = 20;
|
||||||
configValues["general:col.active_border"].intValue = 0xffffffff;
|
configValues["general:col.active_border"].intValue = 0xffffffff;
|
||||||
configValues["general:col.inactive_border"].intValue = 0xff444444;
|
configValues["general:col.inactive_border"].intValue = 0xff444444;
|
||||||
|
configValues["general:cursor_inactive_timeout"].intValue = 0;
|
||||||
|
|
||||||
configValues["debug:int"].intValue = 0;
|
configValues["debug:int"].intValue = 0;
|
||||||
configValues["debug:log_damage"].intValue = 0;
|
configValues["debug:log_damage"].intValue = 0;
|
||||||
@@ -45,7 +47,13 @@ void CConfigManager::setDefaultVars() {
|
|||||||
configValues["decoration:active_opacity"].floatValue = 1;
|
configValues["decoration:active_opacity"].floatValue = 1;
|
||||||
configValues["decoration:inactive_opacity"].floatValue = 1;
|
configValues["decoration:inactive_opacity"].floatValue = 1;
|
||||||
configValues["decoration:fullscreen_opacity"].floatValue = 1;
|
configValues["decoration:fullscreen_opacity"].floatValue = 1;
|
||||||
configValues["decoration:multisample_edges"].intValue = 0;
|
configValues["decoration:multisample_edges"].intValue = 1;
|
||||||
|
configValues["decoration:no_blur_on_oversized"].intValue = 1;
|
||||||
|
configValues["decoration:drop_shadow"].intValue = 1;
|
||||||
|
configValues["decoration:shadow_range"].intValue = 4;
|
||||||
|
configValues["decoration:shadow_render_power"].intValue = 3;
|
||||||
|
configValues["decoration:shadow_ignore_window"].intValue = 1;
|
||||||
|
configValues["decoration:col.shadow"].intValue = 0xee1a1a1a;
|
||||||
|
|
||||||
configValues["dwindle:pseudotile"].intValue = 0;
|
configValues["dwindle:pseudotile"].intValue = 0;
|
||||||
configValues["dwindle:col.group_border"].intValue = 0x66777700;
|
configValues["dwindle:col.group_border"].intValue = 0x66777700;
|
||||||
@@ -74,7 +82,7 @@ void CConfigManager::setDefaultVars() {
|
|||||||
configValues["animations:workspaces_speed"].floatValue = 0.f;
|
configValues["animations:workspaces_speed"].floatValue = 0.f;
|
||||||
configValues["animations:workspaces"].intValue = 1;
|
configValues["animations:workspaces"].intValue = 1;
|
||||||
|
|
||||||
configValues["input:kb_layout"].strValue = "en";
|
configValues["input:kb_layout"].strValue = "us";
|
||||||
configValues["input:kb_variant"].strValue = STRVAL_EMPTY;
|
configValues["input:kb_variant"].strValue = STRVAL_EMPTY;
|
||||||
configValues["input:kb_options"].strValue = STRVAL_EMPTY;
|
configValues["input:kb_options"].strValue = STRVAL_EMPTY;
|
||||||
configValues["input:kb_rules"].strValue = STRVAL_EMPTY;
|
configValues["input:kb_rules"].strValue = STRVAL_EMPTY;
|
||||||
@@ -84,7 +92,11 @@ void CConfigManager::setDefaultVars() {
|
|||||||
configValues["input:natural_scroll"].intValue = 0;
|
configValues["input:natural_scroll"].intValue = 0;
|
||||||
configValues["input:numlock_by_default"].intValue = 0;
|
configValues["input:numlock_by_default"].intValue = 0;
|
||||||
configValues["input:force_no_accel"].intValue = 0;
|
configValues["input:force_no_accel"].intValue = 0;
|
||||||
|
configValues["input:touchpad:natural_scroll"].intValue = 0;
|
||||||
configValues["input:touchpad:disable_while_typing"].intValue = 1;
|
configValues["input:touchpad:disable_while_typing"].intValue = 1;
|
||||||
|
configValues["input:touchpad:clickfinger_behavior"].intValue = 0;
|
||||||
|
configValues["input:touchpad:middle_button_emulation"].intValue = 0;
|
||||||
|
configValues["input:touchpad:tap-to-click"].intValue = 1;
|
||||||
|
|
||||||
configValues["input:follow_mouse"].intValue = 1;
|
configValues["input:follow_mouse"].intValue = 1;
|
||||||
|
|
||||||
@@ -156,11 +168,57 @@ void CConfigManager::configSetValueSafe(const std::string& COMMAND, const std::s
|
|||||||
|
|
||||||
void CConfigManager::handleRawExec(const std::string& command, const std::string& args) {
|
void CConfigManager::handleRawExec(const std::string& command, const std::string& args) {
|
||||||
// Exec in the background dont wait for it.
|
// Exec in the background dont wait for it.
|
||||||
if (fork() == 0) {
|
|
||||||
execl("/bin/sh", "/bin/sh", "-c", args.c_str(), nullptr);
|
|
||||||
|
|
||||||
|
std::string toExec = args;
|
||||||
|
|
||||||
|
if (g_pXWaylandManager->m_sWLRXWayland)
|
||||||
|
toExec = std::string("WAYLAND_DISPLAY=") + std::string(g_pCompositor->m_szWLDisplaySocket) + " DISPLAY=" + std::string(g_pXWaylandManager->m_sWLRXWayland->display_name) + " " + toExec;
|
||||||
|
else
|
||||||
|
toExec = std::string("WAYLAND_DISPLAY=") + std::string(g_pCompositor->m_szWLDisplaySocket) + " " + toExec;
|
||||||
|
|
||||||
|
Debug::log(LOG, "Config executing %s", toExec.c_str());
|
||||||
|
|
||||||
|
int socket[2];
|
||||||
|
if (pipe(socket) != 0) {
|
||||||
|
Debug::log(LOG, "Unable to create pipe for fork");
|
||||||
|
}
|
||||||
|
|
||||||
|
pid_t child, grandchild;
|
||||||
|
child = fork();
|
||||||
|
if (child < 0) {
|
||||||
|
close(socket[0]);
|
||||||
|
close(socket[1]);
|
||||||
|
Debug::log(LOG, "Fail to create the first fork");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (child == 0) {
|
||||||
|
// run in child
|
||||||
|
grandchild = fork();
|
||||||
|
if (grandchild == 0) {
|
||||||
|
// run in grandchild
|
||||||
|
close(socket[0]);
|
||||||
|
close(socket[1]);
|
||||||
|
execl("/bin/sh", "/bin/sh", "-c", args.c_str(), nullptr);
|
||||||
|
// exit grandchild
|
||||||
_exit(0);
|
_exit(0);
|
||||||
}
|
}
|
||||||
|
close(socket[0]);
|
||||||
|
write(socket[1], &grandchild, sizeof(grandchild));
|
||||||
|
close(socket[1]);
|
||||||
|
// exit child
|
||||||
|
_exit(0);
|
||||||
|
}
|
||||||
|
// run in parent
|
||||||
|
close(socket[1]);
|
||||||
|
read(socket[0], &grandchild, sizeof(grandchild));
|
||||||
|
close(socket[0]);
|
||||||
|
// clear child and leave child to init
|
||||||
|
waitpid(child, NULL, 0);
|
||||||
|
if (child < 0) {
|
||||||
|
Debug::log(LOG, "Fail to create the second fork");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Debug::log(LOG, "Process created with pid %d", grandchild);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CConfigManager::handleMonitor(const std::string& command, const std::string& args) {
|
void CConfigManager::handleMonitor(const std::string& command, const std::string& args) {
|
||||||
@@ -365,7 +423,7 @@ void CConfigManager::handleAnimation(const std::string& command, const std::stri
|
|||||||
configSetValueSafe("animations:" + ANIMNAME + "_style", curitem);
|
configSetValueSafe("animations:" + ANIMNAME + "_style", curitem);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CConfigManager::handleBind(const std::string& command, const std::string& value) {
|
void CConfigManager::handleBind(const std::string& command, const std::string& value, bool locked) {
|
||||||
// example:
|
// example:
|
||||||
// bind=SUPER,G,exec,dmenu_run <args>
|
// bind=SUPER,G,exec,dmenu_run <args>
|
||||||
|
|
||||||
@@ -398,7 +456,7 @@ void CConfigManager::handleBind(const std::string& command, const std::string& v
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (KEY != "")
|
if (KEY != "")
|
||||||
g_pKeybindManager->addKeybind(SKeybind{KEY, MOD, HANDLER, COMMAND});
|
g_pKeybindManager->addKeybind(SKeybind{KEY, MOD, HANDLER, COMMAND, locked, m_szCurrentSubmap});
|
||||||
}
|
}
|
||||||
|
|
||||||
void CConfigManager::handleUnbind(const std::string& command, const std::string& value) {
|
void CConfigManager::handleUnbind(const std::string& command, const std::string& value) {
|
||||||
@@ -429,7 +487,9 @@ void CConfigManager::handleWindowRule(const std::string& command, const std::str
|
|||||||
&& RULE.find("size") != 0
|
&& RULE.find("size") != 0
|
||||||
&& RULE.find("pseudo") != 0
|
&& RULE.find("pseudo") != 0
|
||||||
&& RULE.find("monitor") != 0
|
&& RULE.find("monitor") != 0
|
||||||
&& RULE.find("nofocus") != 0
|
&& RULE != "nofocus"
|
||||||
|
&& RULE != "noblur"
|
||||||
|
&& RULE != "fullscreen"
|
||||||
&& RULE.find("animation") != 0
|
&& RULE.find("animation") != 0
|
||||||
&& RULE.find("rounding") != 0
|
&& RULE.find("rounding") != 0
|
||||||
&& RULE.find("workspace") != 0) {
|
&& RULE.find("workspace") != 0) {
|
||||||
@@ -445,16 +505,23 @@ void CConfigManager::handleWindowRule(const std::string& command, const std::str
|
|||||||
void CConfigManager::handleDefaultWorkspace(const std::string& command, const std::string& value) {
|
void CConfigManager::handleDefaultWorkspace(const std::string& command, const std::string& value) {
|
||||||
|
|
||||||
const auto DISPLAY = value.substr(0, value.find_first_of(','));
|
const auto DISPLAY = value.substr(0, value.find_first_of(','));
|
||||||
const auto WORKSPACEID = stoi(value.substr(value.find_first_of(',') + 1));
|
const auto WORKSPACE = value.substr(value.find_first_of(',') + 1);
|
||||||
|
|
||||||
for (auto& mr : m_dMonitorRules) {
|
for (auto& mr : m_dMonitorRules) {
|
||||||
if (mr.name == DISPLAY) {
|
if (mr.name == DISPLAY) {
|
||||||
mr.defaultWorkspaceID = WORKSPACEID;
|
mr.defaultWorkspace = WORKSPACE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CConfigManager::handleSubmap(const std::string& command, const std::string& submap) {
|
||||||
|
if (submap == "reset")
|
||||||
|
m_szCurrentSubmap = "";
|
||||||
|
else
|
||||||
|
m_szCurrentSubmap = submap;
|
||||||
|
}
|
||||||
|
|
||||||
void CConfigManager::handleSource(const std::string& command, const std::string& rawpath) {
|
void CConfigManager::handleSource(const std::string& command, const std::string& rawpath) {
|
||||||
static const char* const ENVHOME = getenv("HOME");
|
static const char* const ENVHOME = getenv("HOME");
|
||||||
|
|
||||||
@@ -528,12 +595,14 @@ std::string CConfigManager::parseKeyword(const std::string& COMMAND, const std::
|
|||||||
}
|
}
|
||||||
else if (COMMAND == "monitor") handleMonitor(COMMAND, VALUE);
|
else if (COMMAND == "monitor") handleMonitor(COMMAND, VALUE);
|
||||||
else if (COMMAND == "bind") handleBind(COMMAND, VALUE);
|
else if (COMMAND == "bind") handleBind(COMMAND, VALUE);
|
||||||
|
else if (COMMAND == "bindl") handleBind(COMMAND, VALUE, true);
|
||||||
else if (COMMAND == "unbind") handleUnbind(COMMAND, VALUE);
|
else if (COMMAND == "unbind") handleUnbind(COMMAND, VALUE);
|
||||||
else if (COMMAND == "workspace") handleDefaultWorkspace(COMMAND, VALUE);
|
else if (COMMAND == "workspace") handleDefaultWorkspace(COMMAND, VALUE);
|
||||||
else if (COMMAND == "windowrule") handleWindowRule(COMMAND, VALUE);
|
else if (COMMAND == "windowrule") handleWindowRule(COMMAND, VALUE);
|
||||||
else if (COMMAND == "bezier") handleBezier(COMMAND, VALUE);
|
else if (COMMAND == "bezier") handleBezier(COMMAND, VALUE);
|
||||||
else if (COMMAND == "animation") handleAnimation(COMMAND, VALUE);
|
else if (COMMAND == "animation") handleAnimation(COMMAND, VALUE);
|
||||||
else if (COMMAND == "source") handleSource(COMMAND, VALUE);
|
else if (COMMAND == "source") handleSource(COMMAND, VALUE);
|
||||||
|
else if (COMMAND == "submap") handleSubmap(COMMAND, VALUE);
|
||||||
else
|
else
|
||||||
configSetValueSafe(currentCategory + (currentCategory == "" ? "" : ":") + COMMAND, VALUE);
|
configSetValueSafe(currentCategory + (currentCategory == "" ? "" : ":") + COMMAND, VALUE);
|
||||||
|
|
||||||
@@ -640,7 +709,8 @@ void CConfigManager::loadConfigLoadVars() {
|
|||||||
configPaths.clear();
|
configPaths.clear();
|
||||||
|
|
||||||
static const char* const ENVHOME = getenv("HOME");
|
static const char* const ENVHOME = getenv("HOME");
|
||||||
const std::string CONFIGPATH = ENVHOME + (ISDEBUG ? (std::string) "/.config/hypr/hyprlandd.conf" : (std::string) "/.config/hypr/hyprland.conf");
|
const std::string CONFIGPARENTPATH = ENVHOME + (std::string) "/.config/hypr/";
|
||||||
|
const std::string CONFIGPATH = CONFIGPARENTPATH + (ISDEBUG ? "hyprlandd.conf" : "hyprland.conf");
|
||||||
|
|
||||||
configPaths.push_back(CONFIGPATH);
|
configPaths.push_back(CONFIGPATH);
|
||||||
|
|
||||||
@@ -653,6 +723,15 @@ void CConfigManager::loadConfigLoadVars() {
|
|||||||
std::filesystem::rename(CONFIGPATH, CONFIGPATH + ".backup");
|
std::filesystem::rename(CONFIGPATH, CONFIGPATH + ".backup");
|
||||||
} catch(...) { /* Probably doesn't exist */}
|
} catch(...) { /* Probably doesn't exist */}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (!std::filesystem::is_directory(CONFIGPARENTPATH))
|
||||||
|
std::filesystem::create_directories(CONFIGPARENTPATH);
|
||||||
|
}
|
||||||
|
catch (...) {
|
||||||
|
parseError = "Broken config file! (Could not create directory)";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
std::ofstream ofs;
|
std::ofstream ofs;
|
||||||
ofs.open(CONFIGPATH, std::ios::trunc);
|
ofs.open(CONFIGPATH, std::ios::trunc);
|
||||||
|
|
||||||
@@ -840,15 +919,26 @@ std::vector<SWindowRule> CConfigManager::getMatchingRules(CWindow* pWindow) {
|
|||||||
std::string title = g_pXWaylandManager->getTitle(pWindow);
|
std::string title = g_pXWaylandManager->getTitle(pWindow);
|
||||||
std::string appidclass = g_pXWaylandManager->getAppIDClass(pWindow);
|
std::string appidclass = g_pXWaylandManager->getAppIDClass(pWindow);
|
||||||
|
|
||||||
|
Debug::log(LOG, "Searching for matching rules for %s (title: %s)", appidclass.c_str(), title.c_str());
|
||||||
|
|
||||||
for (auto& rule : m_dWindowRules) {
|
for (auto& rule : m_dWindowRules) {
|
||||||
// check if we have a matching rule
|
// check if we have a matching rule
|
||||||
try {
|
try {
|
||||||
|
if (rule.szValue.find("title:") == 0) {
|
||||||
|
// we have a title rule.
|
||||||
|
std::regex RULECHECK(rule.szValue.substr(6));
|
||||||
|
|
||||||
|
if (!std::regex_search(title, RULECHECK))
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
std::regex classCheck(rule.szValue);
|
std::regex classCheck(rule.szValue);
|
||||||
|
|
||||||
if (!std::regex_search(title, classCheck) && !std::regex_search(appidclass, classCheck))
|
if (!std::regex_search(appidclass, classCheck))
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
Debug::log(ERR, "Regex error at %s", rule.szValue.c_str());
|
Debug::log(ERR, "Regex error at %s", rule.szValue.c_str());
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// applies. Read the rule and behave accordingly
|
// applies. Read the rule and behave accordingly
|
||||||
|
@@ -28,7 +28,7 @@ struct SMonitorRule {
|
|||||||
Vector2D offset = Vector2D(0,0);
|
Vector2D offset = Vector2D(0,0);
|
||||||
float scale = 1;
|
float scale = 1;
|
||||||
float refreshRate = 60;
|
float refreshRate = 60;
|
||||||
int defaultWorkspaceID = -1;
|
std::string defaultWorkspace = "";
|
||||||
bool disabled = false;
|
bool disabled = false;
|
||||||
wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
||||||
};
|
};
|
||||||
@@ -88,6 +88,8 @@ private:
|
|||||||
|
|
||||||
std::string parseError = ""; // For storing a parse error to display later
|
std::string parseError = ""; // For storing a parse error to display later
|
||||||
|
|
||||||
|
std::string m_szCurrentSubmap = ""; // For storing the current keybind submap
|
||||||
|
|
||||||
bool isFirstLaunch = true; // For exec-once
|
bool isFirstLaunch = true; // For exec-once
|
||||||
|
|
||||||
std::deque<SMonitorRule> m_dMonitorRules;
|
std::deque<SMonitorRule> m_dMonitorRules;
|
||||||
@@ -106,13 +108,14 @@ private:
|
|||||||
void configSetValueSafe(const std::string&, const std::string&);
|
void configSetValueSafe(const std::string&, const std::string&);
|
||||||
void handleRawExec(const std::string&, const std::string&);
|
void handleRawExec(const std::string&, const std::string&);
|
||||||
void handleMonitor(const std::string&, const std::string&);
|
void handleMonitor(const std::string&, const std::string&);
|
||||||
void handleBind(const std::string&, const std::string&);
|
void handleBind(const std::string&, const std::string&, bool locked = false);
|
||||||
void handleUnbind(const std::string&, const std::string&);
|
void handleUnbind(const std::string&, const std::string&);
|
||||||
void handleWindowRule(const std::string&, const std::string&);
|
void handleWindowRule(const std::string&, const std::string&);
|
||||||
void handleDefaultWorkspace(const std::string&, const std::string&);
|
void handleDefaultWorkspace(const std::string&, const std::string&);
|
||||||
void handleBezier(const std::string&, const std::string&);
|
void handleBezier(const std::string&, const std::string&);
|
||||||
void handleAnimation(const std::string&, const std::string&);
|
void handleAnimation(const std::string&, const std::string&);
|
||||||
void handleSource(const std::string&, const std::string&);
|
void handleSource(const std::string&, const std::string&);
|
||||||
|
void handleSubmap(const std::string&, const std::string&);
|
||||||
};
|
};
|
||||||
|
|
||||||
inline std::unique_ptr<CConfigManager> g_pConfigManager;
|
inline std::unique_ptr<CConfigManager> g_pConfigManager;
|
@@ -24,8 +24,7 @@ input {
|
|||||||
}
|
}
|
||||||
|
|
||||||
general {
|
general {
|
||||||
max_fps=60 # deprecated, unused
|
sensitivity=1.0 # for mouse cursor
|
||||||
sensitivity=0.25
|
|
||||||
main_mod=SUPER
|
main_mod=SUPER
|
||||||
|
|
||||||
gaps_in=5
|
gaps_in=5
|
||||||
@@ -34,6 +33,8 @@ general {
|
|||||||
col.active_border=0x66ee1111
|
col.active_border=0x66ee1111
|
||||||
col.inactive_border=0x66333333
|
col.inactive_border=0x66333333
|
||||||
|
|
||||||
|
apply_sens_to_raw=0 # whether to apply the sensitivity to raw input (e.g. used by games where you aim using your mouse)
|
||||||
|
|
||||||
damage_tracking=full # leave it on full unless you hate your GPU and want to make it suffer
|
damage_tracking=full # leave it on full unless you hate your GPU and want to make it suffer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -88,6 +88,20 @@ std::string devicesRequest() {
|
|||||||
result += getFormat("\tKeyboard at %x:\n\t\t%s\n", &k, k.keyboard->name);
|
result += getFormat("\tKeyboard at %x:\n\t\t%s\n", &k, k.keyboard->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
result += "\n\nTablets:\n";
|
||||||
|
|
||||||
|
for (auto& d : g_pInputManager->m_lTabletPads) {
|
||||||
|
result += getFormat("\tTablet Pad at %x (belongs to %x -> %s)\n", &d, d.pTabletParent, d.pTabletParent ? d.pTabletParent->wlrDevice ? d.pTabletParent->wlrDevice->name : "" : "");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& d : g_pInputManager->m_lTablets) {
|
||||||
|
result += getFormat("\tTablet at %x:\n\t\t%s\n", &d, d.wlrDevice ? d.wlrDevice->name : "");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& d : g_pInputManager->m_lTabletTools) {
|
||||||
|
result += getFormat("\tTablet Tool at %x (belongs to %x)\n", &d, d.wlrTabletTool ? d.wlrTabletTool->data : 0);
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,6 +114,9 @@ std::string versionRequest() {
|
|||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
result += "debug\n";
|
result += "debug\n";
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef HYPRLAND_DEBUG
|
||||||
|
result += "debug\n";
|
||||||
|
#endif
|
||||||
#ifdef NO_XWAYLAND
|
#ifdef NO_XWAYLAND
|
||||||
result += "no xwayland\n";
|
result += "no xwayland\n";
|
||||||
#endif
|
#endif
|
||||||
|
@@ -31,6 +31,9 @@ void Debug::log(LogLevel level, const char* fmt, ...) {
|
|||||||
case CRIT:
|
case CRIT:
|
||||||
ofs << "[CRITICAL] ";
|
ofs << "[CRITICAL] ";
|
||||||
break;
|
break;
|
||||||
|
case INFO:
|
||||||
|
ofs << "[INFO] ";
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@@ -8,7 +8,8 @@ enum LogLevel {
|
|||||||
LOG = 0,
|
LOG = 0,
|
||||||
WARN,
|
WARN,
|
||||||
ERR,
|
ERR,
|
||||||
CRIT
|
CRIT,
|
||||||
|
INFO
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace Debug {
|
namespace Debug {
|
||||||
|
@@ -7,10 +7,14 @@
|
|||||||
#include "wlrunstable/wlr_ext_workspace_v1.hpp"
|
#include "wlrunstable/wlr_ext_workspace_v1.hpp"
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
|
#ifdef HYPRLAND_DEBUG
|
||||||
#define ISDEBUG true
|
#define ISDEBUG true
|
||||||
#else
|
#else
|
||||||
#define ISDEBUG false
|
#define ISDEBUG false
|
||||||
#endif
|
#endif
|
||||||
|
#else
|
||||||
|
#define ISDEBUG false
|
||||||
|
#endif
|
||||||
|
|
||||||
#define RIP(format, ... ) { fprintf(stderr, format "\n", ##__VA_ARGS__); exit(EXIT_FAILURE); }
|
#define RIP(format, ... ) { fprintf(stderr, format "\n", ##__VA_ARGS__); exit(EXIT_FAILURE); }
|
||||||
|
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
#include "../Compositor.hpp"
|
#include "../Compositor.hpp"
|
||||||
#include "../helpers/WLClasses.hpp"
|
#include "../helpers/WLClasses.hpp"
|
||||||
#include "../managers/InputManager.hpp"
|
#include "../managers/input/InputManager.hpp"
|
||||||
#include "../render/Renderer.hpp"
|
#include "../render/Renderer.hpp"
|
||||||
|
|
||||||
// ---------------------------------------------------- //
|
// ---------------------------------------------------- //
|
||||||
@@ -57,6 +57,15 @@ void Events::listener_mouseAxis(wl_listener* listener, void* data) {
|
|||||||
void Events::listener_requestMouse(wl_listener* listener, void* data) {
|
void Events::listener_requestMouse(wl_listener* listener, void* data) {
|
||||||
const auto EVENT = (wlr_seat_pointer_request_set_cursor_event*)data;
|
const auto EVENT = (wlr_seat_pointer_request_set_cursor_event*)data;
|
||||||
|
|
||||||
|
if (!g_pHyprRenderer->shouldRenderCursor())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!EVENT->surface) {
|
||||||
|
g_pHyprRenderer->m_bWindowRequestedCursorHide = true;
|
||||||
|
} else {
|
||||||
|
g_pHyprRenderer->m_bWindowRequestedCursorHide = false;
|
||||||
|
}
|
||||||
|
|
||||||
if (EVENT->seat_client == g_pCompositor->m_sSeat.seat->pointer_state.focused_client)
|
if (EVENT->seat_client == g_pCompositor->m_sSeat.seat->pointer_state.focused_client)
|
||||||
wlr_cursor_set_surface(g_pCompositor->m_sWLRCursor, EVENT->surface, EVENT->hotspot_x, EVENT->hotspot_y);
|
wlr_cursor_set_surface(g_pCompositor->m_sWLRCursor, EVENT->surface, EVENT->hotspot_x, EVENT->hotspot_y);
|
||||||
}
|
}
|
||||||
@@ -73,13 +82,25 @@ void Events::listener_newInput(wl_listener* listener, void* data) {
|
|||||||
Debug::log(LOG, "Attached a mouse with name %s", DEVICE->name);
|
Debug::log(LOG, "Attached a mouse with name %s", DEVICE->name);
|
||||||
g_pInputManager->newMouse(DEVICE);
|
g_pInputManager->newMouse(DEVICE);
|
||||||
break;
|
break;
|
||||||
|
case WLR_INPUT_DEVICE_TOUCH:
|
||||||
|
Debug::log(LOG, "Attached a touch device with name %s", DEVICE->name);
|
||||||
|
Debug::log(WARN, "!!!! Hyprland does not directly support touchscreens, bugs may occur !!!!");
|
||||||
|
wlr_cursor_attach_input_device(g_pCompositor->m_sWLRCursor, DEVICE);
|
||||||
|
break;
|
||||||
|
case WLR_INPUT_DEVICE_TABLET_TOOL:
|
||||||
|
Debug::log(LOG, "Attached a tablet tool with name %s", DEVICE->name);
|
||||||
|
g_pInputManager->newTabletTool(DEVICE);
|
||||||
|
break;
|
||||||
|
case WLR_INPUT_DEVICE_TABLET_PAD:
|
||||||
|
Debug::log(LOG, "Attached a tablet pad with name %s", DEVICE->name);
|
||||||
|
g_pInputManager->newTabletPad(DEVICE);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
|
Debug::log(WARN, "Unrecognized input device plugged in: %s", DEVICE->name);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t capabilities = WL_SEAT_CAPABILITY_POINTER | WL_SEAT_CAPABILITY_KEYBOARD;
|
g_pInputManager->updateCapabilities(DEVICE);
|
||||||
|
|
||||||
wlr_seat_set_capabilities(g_pCompositor->m_sSeat.seat, capabilities);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Events::listener_newConstraint(wl_listener* listener, void* data) {
|
void Events::listener_newConstraint(wl_listener* listener, void* data) {
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
#include "../Compositor.hpp"
|
#include "../Compositor.hpp"
|
||||||
#include "../helpers/WLClasses.hpp"
|
#include "../helpers/WLClasses.hpp"
|
||||||
#include "../managers/InputManager.hpp"
|
#include "../managers/input/InputManager.hpp"
|
||||||
#include "../render/Renderer.hpp"
|
#include "../render/Renderer.hpp"
|
||||||
#include "Events.hpp"
|
#include "Events.hpp"
|
||||||
|
|
||||||
@@ -26,7 +26,7 @@ void Events::listener_newLayerSurface(wl_listener* listener, void* data) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug::log(LOG, "New LayerSurface has no preferred monitor. Assigning Monitor %s", PMONITOR->szName);
|
Debug::log(LOG, "New LayerSurface has no preferred monitor. Assigning Monitor %s", PMONITOR->szName.c_str());
|
||||||
|
|
||||||
WLRLAYERSURFACE->output = PMONITOR->output;
|
WLRLAYERSURFACE->output = PMONITOR->output;
|
||||||
}
|
}
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
#include "../Compositor.hpp"
|
#include "../Compositor.hpp"
|
||||||
#include "../helpers/WLClasses.hpp"
|
#include "../helpers/WLClasses.hpp"
|
||||||
#include "../managers/InputManager.hpp"
|
#include "../managers/input/InputManager.hpp"
|
||||||
#include "../render/Renderer.hpp"
|
#include "../render/Renderer.hpp"
|
||||||
|
|
||||||
// ------------------------------ //
|
// ------------------------------ //
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
#include "../Compositor.hpp"
|
#include "../Compositor.hpp"
|
||||||
#include "../helpers/WLClasses.hpp"
|
#include "../helpers/WLClasses.hpp"
|
||||||
#include "../managers/InputManager.hpp"
|
#include "../managers/input/InputManager.hpp"
|
||||||
#include "../render/Renderer.hpp"
|
#include "../render/Renderer.hpp"
|
||||||
#include "Events.hpp"
|
#include "Events.hpp"
|
||||||
#include "../debug/HyprCtl.hpp"
|
#include "../debug/HyprCtl.hpp"
|
||||||
@@ -114,7 +114,15 @@ void Events::listener_newOutput(wl_listener* listener, void* data) {
|
|||||||
wlr_ext_workspace_group_handle_v1_output_enter(PNEWMONITOR->pWLRWorkspaceGroupHandle, PNEWMONITOR->output);
|
wlr_ext_workspace_group_handle_v1_output_enter(PNEWMONITOR->pWLRWorkspaceGroupHandle, PNEWMONITOR->output);
|
||||||
|
|
||||||
// Workspace
|
// Workspace
|
||||||
const auto WORKSPACEID = monitorRule.defaultWorkspaceID == -1 ? g_pCompositor->m_lWorkspaces.size() + 1 /* Cuz workspaces doesnt have the new one yet and we start with 1 */ : monitorRule.defaultWorkspaceID;
|
std::string newDefaultWorkspaceName = "";
|
||||||
|
auto WORKSPACEID = monitorRule.defaultWorkspace == "" ? g_pCompositor->m_lWorkspaces.size() + 1 : getWorkspaceIDFromString(monitorRule.defaultWorkspace, newDefaultWorkspaceName);
|
||||||
|
|
||||||
|
if (WORKSPACEID == INT_MAX || WORKSPACEID == (long unsigned int)SPECIAL_WORKSPACE_ID) {
|
||||||
|
WORKSPACEID = g_pCompositor->m_lWorkspaces.size() + 1;
|
||||||
|
newDefaultWorkspaceName = std::to_string(WORKSPACEID);
|
||||||
|
|
||||||
|
Debug::log(LOG, "Invalid workspace= directive name in monitor parsing, workspace name \"%s\" is invalid.", monitorRule.defaultWorkspace);
|
||||||
|
}
|
||||||
|
|
||||||
auto PNEWWORKSPACE = g_pCompositor->getWorkspaceByID(WORKSPACEID);
|
auto PNEWWORKSPACE = g_pCompositor->getWorkspaceByID(WORKSPACEID);
|
||||||
|
|
||||||
@@ -123,20 +131,24 @@ void Events::listener_newOutput(wl_listener* listener, void* data) {
|
|||||||
if (PNEWWORKSPACE) {
|
if (PNEWWORKSPACE) {
|
||||||
// workspace exists, move it to the newly connected monitor
|
// workspace exists, move it to the newly connected monitor
|
||||||
g_pCompositor->moveWorkspaceToMonitor(PNEWWORKSPACE, PNEWMONITOR);
|
g_pCompositor->moveWorkspaceToMonitor(PNEWWORKSPACE, PNEWMONITOR);
|
||||||
|
PNEWMONITOR->activeWorkspace = PNEWWORKSPACE->m_iID;
|
||||||
|
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PNEWMONITOR->ID);
|
||||||
|
PNEWWORKSPACE->startAnim(true,true,true);
|
||||||
} else {
|
} else {
|
||||||
g_pCompositor->m_lWorkspaces.emplace_back(newMonitor.ID);
|
PNEWWORKSPACE = &g_pCompositor->m_lWorkspaces.emplace_back(newMonitor.ID);
|
||||||
PNEWWORKSPACE = &g_pCompositor->m_lWorkspaces.back();
|
|
||||||
|
|
||||||
// We are required to set the name here immediately
|
// We are required to set the name here immediately
|
||||||
wlr_ext_workspace_handle_v1_set_name(PNEWWORKSPACE->m_pWlrHandle, std::to_string(WORKSPACEID).c_str());
|
wlr_ext_workspace_handle_v1_set_name(PNEWWORKSPACE->m_pWlrHandle, newDefaultWorkspaceName.c_str());
|
||||||
|
|
||||||
PNEWWORKSPACE->m_iID = WORKSPACEID;
|
PNEWWORKSPACE->m_iID = WORKSPACEID;
|
||||||
PNEWWORKSPACE->m_szName = std::to_string(WORKSPACEID);
|
PNEWWORKSPACE->m_szName = newDefaultWorkspaceName;
|
||||||
}
|
}
|
||||||
|
|
||||||
PNEWMONITOR->activeWorkspace = PNEWWORKSPACE->m_iID;
|
PNEWMONITOR->activeWorkspace = PNEWWORKSPACE->m_iID;
|
||||||
PNEWMONITOR->scale = monitorRule.scale;
|
PNEWMONITOR->scale = monitorRule.scale;
|
||||||
|
|
||||||
|
PNEWMONITOR->forceFullFrames = 3; // force 3 full frames to make sure there is no blinking due to double-buffering.
|
||||||
|
|
||||||
g_pCompositor->deactivateAllWLRWorkspaces(PNEWWORKSPACE->m_pWlrHandle);
|
g_pCompositor->deactivateAllWLRWorkspaces(PNEWWORKSPACE->m_pWlrHandle);
|
||||||
PNEWWORKSPACE->setActive(true);
|
PNEWWORKSPACE->setActive(true);
|
||||||
|
|
||||||
@@ -160,7 +172,10 @@ void Events::listener_monitorFrame(void* owner, void* data) {
|
|||||||
static std::chrono::high_resolution_clock::time_point startRenderOverlay = std::chrono::high_resolution_clock::now();
|
static std::chrono::high_resolution_clock::time_point startRenderOverlay = std::chrono::high_resolution_clock::now();
|
||||||
static std::chrono::high_resolution_clock::time_point endRenderOverlay = std::chrono::high_resolution_clock::now();
|
static std::chrono::high_resolution_clock::time_point endRenderOverlay = std::chrono::high_resolution_clock::now();
|
||||||
|
|
||||||
if (g_pConfigManager->getInt("debug:overlay") == 1) {
|
static auto *const PDEBUGOVERLAY = &g_pConfigManager->getConfigValuePtr("debug:overlay")->intValue;
|
||||||
|
static auto *const PDAMAGETRACKINGMODE = &g_pConfigManager->getConfigValuePtr("general:damage_tracking_internal")->intValue;
|
||||||
|
|
||||||
|
if (*PDEBUGOVERLAY == 1) {
|
||||||
startRender = std::chrono::high_resolution_clock::now();
|
startRender = std::chrono::high_resolution_clock::now();
|
||||||
g_pDebugOverlay->frameData(PMONITOR);
|
g_pDebugOverlay->frameData(PMONITOR);
|
||||||
}
|
}
|
||||||
@@ -178,6 +193,8 @@ void Events::listener_monitorFrame(void* owner, void* data) {
|
|||||||
|
|
||||||
if (g_pConfigManager->m_bWantsMonitorReload)
|
if (g_pConfigManager->m_bWantsMonitorReload)
|
||||||
g_pConfigManager->performMonitorReload();
|
g_pConfigManager->performMonitorReload();
|
||||||
|
|
||||||
|
g_pHyprRenderer->ensureCursorRenderingMode(); // so that the cursor gets hidden/shown if the user requested timeouts
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PMONITOR->framesToSkip > 0) {
|
if (PMONITOR->framesToSkip > 0) {
|
||||||
@@ -200,9 +217,7 @@ void Events::listener_monitorFrame(void* owner, void* data) {
|
|||||||
bool hasChanged;
|
bool hasChanged;
|
||||||
pixman_region32_init(&damage);
|
pixman_region32_init(&damage);
|
||||||
|
|
||||||
const auto DTMODE = g_pConfigManager->getInt("general:damage_tracking_internal");
|
if (*PDAMAGETRACKINGMODE == -1) {
|
||||||
|
|
||||||
if (DTMODE == -1) {
|
|
||||||
Debug::log(CRIT, "Damage tracking mode -1 ????");
|
Debug::log(CRIT, "Damage tracking mode -1 ????");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -212,7 +227,7 @@ void Events::listener_monitorFrame(void* owner, void* data) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!hasChanged && DTMODE != DAMAGE_TRACKING_NONE) {
|
if (!hasChanged && *PDAMAGETRACKINGMODE != DAMAGE_TRACKING_NONE && PMONITOR->forceFullFrames == 0) {
|
||||||
pixman_region32_fini(&damage);
|
pixman_region32_fini(&damage);
|
||||||
wlr_output_rollback(PMONITOR->output);
|
wlr_output_rollback(PMONITOR->output);
|
||||||
wlr_output_schedule_frame(PMONITOR->output); // we update shit at the monitor's Hz so we need to schedule frames because rollback wont
|
wlr_output_schedule_frame(PMONITOR->output); // we update shit at the monitor's Hz so we need to schedule frames because rollback wont
|
||||||
@@ -220,19 +235,19 @@ void Events::listener_monitorFrame(void* owner, void* data) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// if we have no tracking or full tracking, invalidate the entire monitor
|
// if we have no tracking or full tracking, invalidate the entire monitor
|
||||||
if (DTMODE == DAMAGE_TRACKING_NONE || DTMODE == DAMAGE_TRACKING_MONITOR) {
|
if (*PDAMAGETRACKINGMODE == DAMAGE_TRACKING_NONE || *PDAMAGETRACKINGMODE == DAMAGE_TRACKING_MONITOR || PMONITOR->forceFullFrames > 0) {
|
||||||
pixman_region32_union_rect(&damage, &damage, 0, 0, (int)PMONITOR->vecTransformedSize.x, (int)PMONITOR->vecTransformedSize.y);
|
pixman_region32_union_rect(&damage, &damage, 0, 0, (int)PMONITOR->vecTransformedSize.x, (int)PMONITOR->vecTransformedSize.y);
|
||||||
|
|
||||||
pixman_region32_copy(&g_pHyprOpenGL->m_rOriginalDamageRegion, &damage);
|
pixman_region32_copy(&g_pHyprOpenGL->m_rOriginalDamageRegion, &damage);
|
||||||
} else {
|
} else {
|
||||||
|
static auto* const PBLURENABLED = &g_pConfigManager->getConfigValuePtr("decoration:blur")->intValue;
|
||||||
|
|
||||||
// if we use blur we need to expand the damage for proper blurring
|
// if we use blur we need to expand the damage for proper blurring
|
||||||
if (g_pConfigManager->getInt("decoration:blur") == 1) {
|
if (*PBLURENABLED == 1) {
|
||||||
// TODO: can this be optimized?
|
// TODO: can this be optimized?
|
||||||
const auto BLURSIZE = g_pConfigManager->getInt("decoration:blur_size");
|
static auto* const PBLURSIZE = &g_pConfigManager->getConfigValuePtr("decoration:blur_size")->intValue;
|
||||||
const auto BLURPASSES = g_pConfigManager->getInt("decoration:blur_passes");
|
static auto* const PBLURPASSES = &g_pConfigManager->getConfigValuePtr("decoration:blur_passes")->intValue;
|
||||||
|
const auto BLURRADIUS = *PBLURSIZE * pow(2, *PBLURPASSES); // is this 2^pass? I don't know but it works... I think.
|
||||||
const auto BLURRADIUS = BLURSIZE * pow(2, BLURPASSES); // is this 2^pass? I don't know but it works... I think.
|
|
||||||
|
|
||||||
pixman_region32_copy(&g_pHyprOpenGL->m_rOriginalDamageRegion, &damage);
|
pixman_region32_copy(&g_pHyprOpenGL->m_rOriginalDamageRegion, &damage);
|
||||||
|
|
||||||
@@ -243,6 +258,9 @@ void Events::listener_monitorFrame(void* owner, void* data) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (PMONITOR->forceFullFrames > 0)
|
||||||
|
PMONITOR->forceFullFrames -= 1;
|
||||||
|
|
||||||
// TODO: this is getting called with extents being 0,0,0,0 should it be?
|
// TODO: this is getting called with extents being 0,0,0,0 should it be?
|
||||||
// potentially can save on resources.
|
// potentially can save on resources.
|
||||||
|
|
||||||
@@ -257,7 +275,7 @@ void Events::listener_monitorFrame(void* owner, void* data) {
|
|||||||
g_pHyprError->draw();
|
g_pHyprError->draw();
|
||||||
|
|
||||||
// for drawing the debug overlay
|
// for drawing the debug overlay
|
||||||
if (PMONITOR->ID == 0 && g_pConfigManager->getInt("debug:overlay") == 1) {
|
if (PMONITOR->ID == 0 && *PDEBUGOVERLAY == 1) {
|
||||||
startRenderOverlay = std::chrono::high_resolution_clock::now();
|
startRenderOverlay = std::chrono::high_resolution_clock::now();
|
||||||
g_pDebugOverlay->draw();
|
g_pDebugOverlay->draw();
|
||||||
endRenderOverlay = std::chrono::high_resolution_clock::now();
|
endRenderOverlay = std::chrono::high_resolution_clock::now();
|
||||||
@@ -278,7 +296,7 @@ void Events::listener_monitorFrame(void* owner, void* data) {
|
|||||||
const auto TRANSFORM = wlr_output_transform_invert(PMONITOR->output->transform);
|
const auto TRANSFORM = wlr_output_transform_invert(PMONITOR->output->transform);
|
||||||
wlr_region_transform(&frameDamage, &PMONITOR->damage->current, TRANSFORM, (int)PMONITOR->vecTransformedSize.x, (int)PMONITOR->vecTransformedSize.y);
|
wlr_region_transform(&frameDamage, &PMONITOR->damage->current, TRANSFORM, (int)PMONITOR->vecTransformedSize.x, (int)PMONITOR->vecTransformedSize.y);
|
||||||
|
|
||||||
if (DTMODE == DAMAGE_TRACKING_NONE || DTMODE == DAMAGE_TRACKING_MONITOR)
|
if (*PDAMAGETRACKINGMODE == DAMAGE_TRACKING_NONE || *PDAMAGETRACKINGMODE == DAMAGE_TRACKING_MONITOR)
|
||||||
pixman_region32_union_rect(&frameDamage, &frameDamage, 0, 0, (int)PMONITOR->vecTransformedSize.x, (int)PMONITOR->vecTransformedSize.y);
|
pixman_region32_union_rect(&frameDamage, &frameDamage, 0, 0, (int)PMONITOR->vecTransformedSize.x, (int)PMONITOR->vecTransformedSize.y);
|
||||||
|
|
||||||
wlr_output_set_damage(PMONITOR->output, &frameDamage);
|
wlr_output_set_damage(PMONITOR->output, &frameDamage);
|
||||||
@@ -289,7 +307,7 @@ void Events::listener_monitorFrame(void* owner, void* data) {
|
|||||||
|
|
||||||
wlr_output_schedule_frame(PMONITOR->output);
|
wlr_output_schedule_frame(PMONITOR->output);
|
||||||
|
|
||||||
if (g_pConfigManager->getInt("debug:overlay") == 1) {
|
if (*PDEBUGOVERLAY == 1) {
|
||||||
const float µs = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now() - startRender).count() / 1000.f;
|
const float µs = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now() - startRender).count() / 1000.f;
|
||||||
g_pDebugOverlay->renderData(PMONITOR, µs);
|
g_pDebugOverlay->renderData(PMONITOR, µs);
|
||||||
if (PMONITOR->ID == 0) {
|
if (PMONITOR->ID == 0) {
|
||||||
@@ -318,14 +336,16 @@ void Events::listener_monitorDestroy(void* owner, void* data) {
|
|||||||
|
|
||||||
// Cleanup everything. Move windows back, snap cursor, shit.
|
// Cleanup everything. Move windows back, snap cursor, shit.
|
||||||
const auto BACKUPMON = &g_pCompositor->m_lMonitors.front();
|
const auto BACKUPMON = &g_pCompositor->m_lMonitors.front();
|
||||||
const auto BACKUPWORKSPACE = BACKUPMON->activeWorkspace > 0 ? std::to_string(BACKUPMON->activeWorkspace) : "name:" + g_pCompositor->getWorkspaceByID(BACKUPMON->activeWorkspace)->m_szName;
|
|
||||||
|
|
||||||
if (!BACKUPMON) {
|
if (!BACKUPMON) {
|
||||||
Debug::log(CRIT, "No monitors! Unplugged last! Exiting.");
|
Debug::log(CRIT, "No monitors! Unplugged last! Exiting.");
|
||||||
g_pCompositor->cleanupExit();
|
g_pCompositor->cleanupExit();
|
||||||
|
exit(1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const auto BACKUPWORKSPACE = BACKUPMON->activeWorkspace > 0 ? std::to_string(BACKUPMON->activeWorkspace) : "name:" + g_pCompositor->getWorkspaceByID(BACKUPMON->activeWorkspace)->m_szName;
|
||||||
|
|
||||||
// snap cursor
|
// snap cursor
|
||||||
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sSeat.mouse->mouse, BACKUPMON->vecPosition.x + BACKUPMON->vecTransformedSize.x / 2.f, BACKUPMON->vecPosition.y + BACKUPMON->vecTransformedSize.y / 2.f);
|
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sSeat.mouse->mouse, BACKUPMON->vecPosition.x + BACKUPMON->vecTransformedSize.x / 2.f, BACKUPMON->vecPosition.y + BACKUPMON->vecTransformedSize.y / 2.f);
|
||||||
|
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
#include "../Compositor.hpp"
|
#include "../Compositor.hpp"
|
||||||
#include "../helpers/WLClasses.hpp"
|
#include "../helpers/WLClasses.hpp"
|
||||||
#include "../managers/InputManager.hpp"
|
#include "../managers/input/InputManager.hpp"
|
||||||
#include "../render/Renderer.hpp"
|
#include "../render/Renderer.hpp"
|
||||||
|
|
||||||
// --------------------------------------------- //
|
// --------------------------------------------- //
|
||||||
@@ -26,6 +26,14 @@ void addPopupGlobalCoords(void* pPopup, int* x, int* y) {
|
|||||||
px += curPopup->popup->current.geometry.x;
|
px += curPopup->popup->current.geometry.x;
|
||||||
py += curPopup->popup->current.geometry.y;
|
py += curPopup->popup->current.geometry.y;
|
||||||
|
|
||||||
|
// fix oversized fucking popups
|
||||||
|
// kill me
|
||||||
|
if (curPopup->pSurfaceTree && curPopup->pSurfaceTree->pSurface && !curPopup->parentPopup) {
|
||||||
|
const auto EXTENTSSURFACE = pixman_region32_extents(&curPopup->pSurfaceTree->pSurface->input_region);
|
||||||
|
px -= EXTENTSSURFACE->x1;
|
||||||
|
py -= EXTENTSSURFACE->y1;
|
||||||
|
}
|
||||||
|
|
||||||
if (curPopup->parentPopup) {
|
if (curPopup->parentPopup) {
|
||||||
curPopup = curPopup->parentPopup;
|
curPopup = curPopup->parentPopup;
|
||||||
} else {
|
} else {
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
#include "../Compositor.hpp"
|
#include "../Compositor.hpp"
|
||||||
#include "../helpers/WLClasses.hpp"
|
#include "../helpers/WLClasses.hpp"
|
||||||
#include "../managers/InputManager.hpp"
|
#include "../managers/input/InputManager.hpp"
|
||||||
#include "../render/Renderer.hpp"
|
#include "../render/Renderer.hpp"
|
||||||
|
|
||||||
// ------------------------------------------------------------ //
|
// ------------------------------------------------------------ //
|
||||||
@@ -19,6 +19,14 @@ void addViewCoords(void* pWindow, int* x, int* y) {
|
|||||||
const auto PWINDOW = (CWindow*)pWindow;
|
const auto PWINDOW = (CWindow*)pWindow;
|
||||||
*x += PWINDOW->m_vRealPosition.goalv().x;
|
*x += PWINDOW->m_vRealPosition.goalv().x;
|
||||||
*y += PWINDOW->m_vRealPosition.goalv().y;
|
*y += PWINDOW->m_vRealPosition.goalv().y;
|
||||||
|
|
||||||
|
if (!PWINDOW->m_bIsX11) {
|
||||||
|
wlr_box geom;
|
||||||
|
wlr_xdg_surface_get_geometry(PWINDOW->m_uSurface.xdg, &geom);
|
||||||
|
|
||||||
|
*x -= geom.x;
|
||||||
|
*y -= geom.y;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Events::listener_mapWindow(void* owner, void* data) {
|
void Events::listener_mapWindow(void* owner, void* data) {
|
||||||
@@ -70,7 +78,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
|||||||
|
|
||||||
if (PWORKSPACE->m_bHasFullscreenWindow && !PWINDOW->m_bIsFloating) {
|
if (PWORKSPACE->m_bHasFullscreenWindow && !PWINDOW->m_bIsFloating) {
|
||||||
const auto PFULLWINDOW = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID);
|
const auto PFULLWINDOW = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID);
|
||||||
g_pLayoutManager->getCurrentLayout()->fullscreenRequestForWindow(PFULLWINDOW, FULLSCREEN_FULL);
|
g_pLayoutManager->getCurrentLayout()->fullscreenRequestForWindow(PFULLWINDOW, FULLSCREEN_FULL, false);
|
||||||
g_pXWaylandManager->setWindowFullscreen(PFULLWINDOW, PFULLWINDOW->m_bIsFullscreen);
|
g_pXWaylandManager->setWindowFullscreen(PFULLWINDOW, PFULLWINDOW->m_bIsFullscreen);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,6 +86,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
|||||||
const auto WINDOWRULES = g_pConfigManager->getMatchingRules(PWINDOW);
|
const auto WINDOWRULES = g_pConfigManager->getMatchingRules(PWINDOW);
|
||||||
std::string requestedWorkspace = "";
|
std::string requestedWorkspace = "";
|
||||||
bool workspaceSilent = false;
|
bool workspaceSilent = false;
|
||||||
|
bool requestsFullscreen = false;
|
||||||
|
|
||||||
for (auto& r : WINDOWRULES) {
|
for (auto& r : WINDOWRULES) {
|
||||||
if (r.szRule.find("monitor") == 0) {
|
if (r.szRule.find("monitor") == 0) {
|
||||||
@@ -119,6 +128,10 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
|||||||
PWINDOW->m_bIsPseudotiled = true;
|
PWINDOW->m_bIsPseudotiled = true;
|
||||||
} else if (r.szRule.find("nofocus") == 0) {
|
} else if (r.szRule.find("nofocus") == 0) {
|
||||||
PWINDOW->m_bNoFocus = true;
|
PWINDOW->m_bNoFocus = true;
|
||||||
|
} else if (r.szRule == "noblur") {
|
||||||
|
PWINDOW->m_sAdditionalConfigData.forceNoBlur = true;
|
||||||
|
} else if (r.szRule == "fullscreen") {
|
||||||
|
requestsFullscreen = true;
|
||||||
} else if (r.szRule.find("rounding") == 0) {
|
} else if (r.szRule.find("rounding") == 0) {
|
||||||
try {
|
try {
|
||||||
PWINDOW->m_sAdditionalConfigData.rounding = std::stoi(r.szRule.substr(r.szRule.find_first_of(' ') + 1));
|
PWINDOW->m_sAdditionalConfigData.rounding = std::stoi(r.szRule.substr(r.szRule.find_first_of(' ') + 1));
|
||||||
@@ -215,7 +228,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
|||||||
PWINDOW->m_vPseudoSize = PWINDOW->m_vRealSize.goalv() - Vector2D(10,10);
|
PWINDOW->m_vPseudoSize = PWINDOW->m_vRealSize.goalv() - Vector2D(10,10);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!PWINDOW->m_bNoFocus)
|
if (!PWINDOW->m_bNoFocus && !PWINDOW->m_bNoInitialFocus)
|
||||||
g_pCompositor->focusWindow(PWINDOW);
|
g_pCompositor->focusWindow(PWINDOW);
|
||||||
|
|
||||||
PWINDOW->m_pSurfaceTree = SubsurfaceTree::createTreeRoot(g_pXWaylandManager->getWindowSurface(PWINDOW), addViewCoords, PWINDOW, PWINDOW);
|
PWINDOW->m_pSurfaceTree = SubsurfaceTree::createTreeRoot(g_pXWaylandManager->getWindowSurface(PWINDOW), addViewCoords, PWINDOW, PWINDOW);
|
||||||
@@ -246,6 +259,10 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (requestsFullscreen) {
|
||||||
|
g_pCompositor->setWindowFullscreen(PWINDOW, true, FULLSCREEN_FULL);
|
||||||
|
}
|
||||||
|
|
||||||
Debug::log(LOG, "Map request dispatched, monitor %s, xywh: %f %f %f %f", PMONITOR->szName.c_str(), PWINDOW->m_vRealPosition.goalv().x, PWINDOW->m_vRealPosition.goalv().y, PWINDOW->m_vRealSize.goalv().x, PWINDOW->m_vRealSize.goalv().y);
|
Debug::log(LOG, "Map request dispatched, monitor %s, xywh: %f %f %f %f", PMONITOR->szName.c_str(), PWINDOW->m_vRealPosition.goalv().x, PWINDOW->m_vRealPosition.goalv().y, PWINDOW->m_vRealSize.goalv().x, PWINDOW->m_vRealSize.goalv().y);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -376,9 +393,9 @@ void Events::listener_fullscreenWindow(void* owner, void* data) {
|
|||||||
const auto REQUESTED = &PWINDOW->m_uSurface.xdg->toplevel->requested;
|
const auto REQUESTED = &PWINDOW->m_uSurface.xdg->toplevel->requested;
|
||||||
|
|
||||||
if (REQUESTED->fullscreen != PWINDOW->m_bIsFullscreen)
|
if (REQUESTED->fullscreen != PWINDOW->m_bIsFullscreen)
|
||||||
g_pLayoutManager->getCurrentLayout()->fullscreenRequestForWindow(PWINDOW, FULLSCREEN_FULL);
|
g_pLayoutManager->getCurrentLayout()->fullscreenRequestForWindow(PWINDOW, FULLSCREEN_FULL, true);
|
||||||
} else {
|
} else {
|
||||||
g_pLayoutManager->getCurrentLayout()->fullscreenRequestForWindow(PWINDOW, FULLSCREEN_FULL);
|
g_pLayoutManager->getCurrentLayout()->fullscreenRequestForWindow(PWINDOW, FULLSCREEN_FULL, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug::log(LOG, "Window %x fullscreen to %i", PWINDOW, PWINDOW->m_bIsFullscreen);
|
Debug::log(LOG, "Window %x fullscreen to %i", PWINDOW, PWINDOW->m_bIsFullscreen);
|
||||||
|
@@ -2,6 +2,7 @@
|
|||||||
#include "../defines.hpp"
|
#include "../defines.hpp"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include "../Compositor.hpp"
|
#include "../Compositor.hpp"
|
||||||
|
#include <sys/utsname.h>
|
||||||
|
|
||||||
void addWLSignal(wl_signal* pSignal, wl_listener* pListener, void* pOwner, std::string ownerString) {
|
void addWLSignal(wl_signal* pSignal, wl_listener* pListener, void* pOwner, std::string ownerString) {
|
||||||
ASSERT(pSignal);
|
ASSERT(pSignal);
|
||||||
@@ -158,6 +159,12 @@ int getWorkspaceIDFromString(const std::string& in, std::string& outName) {
|
|||||||
outName = WORKSPACENAME;
|
outName = WORKSPACENAME;
|
||||||
} else {
|
} else {
|
||||||
if (in[0] == 'm') {
|
if (in[0] == 'm') {
|
||||||
|
if (!g_pCompositor->m_pLastMonitor) {
|
||||||
|
Debug::log(ERR, "Relative monitor workspace on monitor null!");
|
||||||
|
result = INT_MAX;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
// monitor relative
|
// monitor relative
|
||||||
result = (int)getPlusMinusKeywordResult(in.substr(1), 0);
|
result = (int)getPlusMinusKeywordResult(in.substr(1), 0);
|
||||||
|
|
||||||
@@ -207,7 +214,14 @@ int getWorkspaceIDFromString(const std::string& in, std::string& outName) {
|
|||||||
outName = g_pCompositor->getWorkspaceByID(currentID)->m_szName;
|
outName = g_pCompositor->getWorkspaceByID(currentID)->m_szName;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
if (g_pCompositor->m_pLastMonitor)
|
||||||
result = std::clamp((int)getPlusMinusKeywordResult(in, g_pCompositor->m_pLastMonitor->activeWorkspace), 1, INT_MAX);
|
result = std::clamp((int)getPlusMinusKeywordResult(in, g_pCompositor->m_pLastMonitor->activeWorkspace), 1, INT_MAX);
|
||||||
|
else if (isNumber(in))
|
||||||
|
result = std::clamp(std::stoi(in), 1, INT_MAX);
|
||||||
|
else {
|
||||||
|
Debug::log(ERR, "Relative workspace on no mon!");
|
||||||
|
result = INT_MAX;
|
||||||
|
}
|
||||||
outName = std::to_string(result);
|
outName = std::to_string(result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -220,3 +234,34 @@ float vecToRectDistanceSquared(const Vector2D& vec, const Vector2D& p1, const Ve
|
|||||||
const float DY = std::max((double)0, std::max(p1.y - vec.y, vec.y - p2.y));
|
const float DY = std::max((double)0, std::max(p1.y - vec.y, vec.y - p2.y));
|
||||||
return DX * DX + DY * DY;
|
return DX * DX + DY * DY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Execute a shell command and get the output
|
||||||
|
std::string execAndGet(const char* cmd) {
|
||||||
|
std::array<char, 128> buffer;
|
||||||
|
std::string result;
|
||||||
|
const std::unique_ptr<FILE, decltype(&pclose)> pipe(popen(cmd, "r"), pclose);
|
||||||
|
if (!pipe) {
|
||||||
|
Debug::log(ERR, "execAndGet: failed in pipe");
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) {
|
||||||
|
result += buffer.data();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void logSystemInfo() {
|
||||||
|
struct utsname unameInfo;
|
||||||
|
|
||||||
|
uname(&unameInfo);
|
||||||
|
|
||||||
|
Debug::log(LOG, "System name: %s", unameInfo.sysname);
|
||||||
|
Debug::log(LOG, "Node name: %s", unameInfo.nodename);
|
||||||
|
Debug::log(LOG, "Release: %s", unameInfo.release);
|
||||||
|
Debug::log(LOG, "Version: %s", unameInfo.version);
|
||||||
|
|
||||||
|
// log etc
|
||||||
|
Debug::log(LOG, "os-release:");
|
||||||
|
|
||||||
|
Debug::log(NONE, "%s", execAndGet("cat /etc/os-release").c_str());
|
||||||
|
}
|
@@ -11,5 +11,7 @@ bool isNumber(const std::string&);
|
|||||||
bool isDirection(const std::string&);
|
bool isDirection(const std::string&);
|
||||||
int getWorkspaceIDFromString(const std::string&, std::string&);
|
int getWorkspaceIDFromString(const std::string&, std::string&);
|
||||||
float vecToRectDistanceSquared(const Vector2D& vec, const Vector2D& p1, const Vector2D& p2);
|
float vecToRectDistanceSquared(const Vector2D& vec, const Vector2D& p1, const Vector2D& p2);
|
||||||
|
void logSystemInfo();
|
||||||
|
std::string execAndGet(const char*);
|
||||||
|
|
||||||
float getPlusMinusKeywordResult(std::string in, float relative);
|
float getPlusMinusKeywordResult(std::string in, float relative);
|
@@ -28,6 +28,7 @@ struct SMonitor {
|
|||||||
float refreshRate = 60;
|
float refreshRate = 60;
|
||||||
wlr_output_damage* damage = nullptr;
|
wlr_output_damage* damage = nullptr;
|
||||||
int framesToSkip = 0;
|
int framesToSkip = 0;
|
||||||
|
int forceFullFrames = 0;
|
||||||
bool noFrameSchedule = false;
|
bool noFrameSchedule = false;
|
||||||
wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
||||||
|
|
||||||
|
17
src/helpers/Timer.cpp
Normal file
17
src/helpers/Timer.cpp
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
#include "Timer.hpp"
|
||||||
|
|
||||||
|
void CTimer::reset() {
|
||||||
|
m_tpLastReset = std::chrono::system_clock::now();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::chrono::system_clock::duration CTimer::getDuration() {
|
||||||
|
return std::chrono::system_clock::now() - m_tpLastReset;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CTimer::getMillis() {
|
||||||
|
return std::chrono::duration_cast<std::chrono::milliseconds>(getDuration()).count();
|
||||||
|
}
|
||||||
|
|
||||||
|
float CTimer::getSeconds() {
|
||||||
|
return std::chrono::duration_cast<std::chrono::milliseconds>(getDuration()).count() / 1000.f;
|
||||||
|
}
|
15
src/helpers/Timer.hpp
Normal file
15
src/helpers/Timer.hpp
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../defines.hpp"
|
||||||
|
|
||||||
|
class CTimer {
|
||||||
|
public:
|
||||||
|
void reset();
|
||||||
|
float getSeconds();
|
||||||
|
int getMillis();
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::chrono::system_clock::time_point m_tpLastReset;
|
||||||
|
|
||||||
|
std::chrono::system_clock::duration getDuration();
|
||||||
|
};
|
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
#include "../events/Events.hpp"
|
#include "../events/Events.hpp"
|
||||||
#include "../defines.hpp"
|
#include "../defines.hpp"
|
||||||
#include "../../wlr-layer-shell-unstable-v1-protocol.h"
|
#include "wlr-layer-shell-unstable-v1-protocol.h"
|
||||||
#include "../Window.hpp"
|
#include "../Window.hpp"
|
||||||
#include "SubsurfaceTree.hpp"
|
#include "SubsurfaceTree.hpp"
|
||||||
#include "AnimatedVariable.hpp"
|
#include "AnimatedVariable.hpp"
|
||||||
@@ -71,6 +71,8 @@ struct SKeyboard {
|
|||||||
|
|
||||||
bool active = false;
|
bool active = false;
|
||||||
|
|
||||||
|
xkb_rule_names currentRules;
|
||||||
|
|
||||||
// For the list lookup
|
// For the list lookup
|
||||||
bool operator==(const SKeyboard& rhs) {
|
bool operator==(const SKeyboard& rhs) {
|
||||||
return keyboard == rhs.keyboard;
|
return keyboard == rhs.keyboard;
|
||||||
@@ -154,3 +156,55 @@ struct SDrag {
|
|||||||
DYNLISTENER(unmapIcon);
|
DYNLISTENER(unmapIcon);
|
||||||
DYNLISTENER(commitIcon);
|
DYNLISTENER(commitIcon);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct STablet {
|
||||||
|
DYNLISTENER(Tip);
|
||||||
|
DYNLISTENER(Axis);
|
||||||
|
DYNLISTENER(Button);
|
||||||
|
DYNLISTENER(Proximity);
|
||||||
|
DYNLISTENER(Destroy);
|
||||||
|
|
||||||
|
wlr_tablet* wlrTablet = nullptr;
|
||||||
|
wlr_tablet_v2_tablet* wlrTabletV2 = nullptr;
|
||||||
|
wlr_input_device* wlrDevice = nullptr;
|
||||||
|
|
||||||
|
bool operator==(const STablet& b) {
|
||||||
|
return wlrDevice == b.wlrDevice;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct STabletTool {
|
||||||
|
wlr_tablet_tool* wlrTabletTool = nullptr;
|
||||||
|
wlr_tablet_v2_tablet_tool* wlrTabletToolV2 = nullptr;
|
||||||
|
|
||||||
|
wlr_tablet_v2_tablet* wlrTabletOwnerV2 = nullptr;
|
||||||
|
|
||||||
|
wlr_surface* pSurface = nullptr;
|
||||||
|
|
||||||
|
double tiltX = 0;
|
||||||
|
double tiltY = 0;
|
||||||
|
|
||||||
|
bool active = true;
|
||||||
|
|
||||||
|
DYNLISTENER(TabletToolDestroy);
|
||||||
|
DYNLISTENER(TabletToolSetCursor);
|
||||||
|
|
||||||
|
bool operator==(const STabletTool& b) {
|
||||||
|
return wlrTabletTool == b.wlrTabletTool;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct STabletPad {
|
||||||
|
wlr_tablet_v2_tablet_pad* wlrTabletPadV2 = nullptr;
|
||||||
|
STablet* pTabletParent = nullptr;
|
||||||
|
|
||||||
|
DYNLISTENER(Attach);
|
||||||
|
DYNLISTENER(Button);
|
||||||
|
DYNLISTENER(Strip);
|
||||||
|
DYNLISTENER(Ring);
|
||||||
|
DYNLISTENER(Destroy);
|
||||||
|
|
||||||
|
bool operator==(const STabletPad& b) {
|
||||||
|
return wlrTabletPadV2 == b.wlrTabletPadV2;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
102
src/includes.hpp
102
src/includes.hpp
@@ -34,56 +34,60 @@
|
|||||||
#define static
|
#define static
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include "../wlroots/include/wlr/backend.h"
|
#include <wlr/backend.h>
|
||||||
#include "../wlroots/include/wlr/backend/libinput.h"
|
#include <wlr/backend/libinput.h>
|
||||||
#include "../wlroots/include/wlr/render/allocator.h"
|
#include <wlr/render/allocator.h>
|
||||||
#include "../wlroots/include/wlr/render/wlr_renderer.h"
|
#include <wlr/render/wlr_renderer.h>
|
||||||
#include "../wlroots/include/wlr/types/wlr_compositor.h"
|
#include <wlr/types/wlr_compositor.h>
|
||||||
#include "../wlroots/include/wlr/types/wlr_cursor.h"
|
#include <wlr/types/wlr_cursor.h>
|
||||||
#include "../wlroots/include/wlr/types/wlr_data_control_v1.h"
|
#include <wlr/types/wlr_data_control_v1.h>
|
||||||
#include "../wlroots/include/wlr/types/wlr_data_device.h"
|
#include <wlr/types/wlr_data_device.h>
|
||||||
#include "../wlroots/include/wlr/types/wlr_export_dmabuf_v1.h"
|
#include <wlr/types/wlr_export_dmabuf_v1.h>
|
||||||
#include "../wlroots/include/wlr/types/wlr_linux_dmabuf_v1.h"
|
#include <wlr/types/wlr_linux_dmabuf_v1.h>
|
||||||
#include "../wlroots/include/wlr/types/wlr_gamma_control_v1.h"
|
#include <wlr/types/wlr_gamma_control_v1.h>
|
||||||
#include "../wlroots/include/wlr/types/wlr_idle.h"
|
#include <wlr/types/wlr_idle.h>
|
||||||
#include "../wlroots/include/wlr/types/wlr_input_device.h"
|
#include <wlr/types/wlr_input_device.h>
|
||||||
#include "../wlroots/include/wlr/types/wlr_keyboard.h"
|
#include <wlr/types/wlr_keyboard.h>
|
||||||
#include "../wlroots/include/wlr/types/wlr_layer_shell_v1.h"
|
#include <wlr/types/wlr_layer_shell_v1.h>
|
||||||
#include "../wlroots/include/wlr/types/wlr_matrix.h"
|
#include <wlr/types/wlr_matrix.h>
|
||||||
#include "../wlroots/include/wlr/types/wlr_output.h"
|
#include <wlr/types/wlr_output.h>
|
||||||
#include "../wlroots/include/wlr/types/wlr_output_layout.h"
|
#include <wlr/types/wlr_output_layout.h>
|
||||||
#include "../wlroots/include/wlr/types/wlr_output_management_v1.h"
|
#include <wlr/types/wlr_output_management_v1.h>
|
||||||
#include "../wlroots/include/wlr/types/wlr_pointer.h"
|
#include <wlr/types/wlr_pointer.h>
|
||||||
#include "../wlroots/include/wlr/types/wlr_presentation_time.h"
|
#include <wlr/types/wlr_presentation_time.h>
|
||||||
#include "../wlroots/include/wlr/types/wlr_primary_selection.h"
|
#include <wlr/types/wlr_primary_selection.h>
|
||||||
#include "../wlroots/include/wlr/types/wlr_primary_selection_v1.h"
|
#include <wlr/types/wlr_primary_selection_v1.h>
|
||||||
#include "../wlroots/include/wlr/types/wlr_screencopy_v1.h"
|
#include <wlr/types/wlr_screencopy_v1.h>
|
||||||
#include "../wlroots/include/wlr/types/wlr_seat.h"
|
#include <wlr/types/wlr_seat.h>
|
||||||
#include "../wlroots/include/wlr/types/wlr_server_decoration.h"
|
#include <wlr/types/wlr_server_decoration.h>
|
||||||
#include "../wlroots/include/wlr/types/wlr_viewporter.h"
|
#include <wlr/types/wlr_viewporter.h>
|
||||||
#include "../wlroots/include/wlr/types/wlr_virtual_keyboard_v1.h"
|
#include <wlr/types/wlr_virtual_keyboard_v1.h>
|
||||||
#include "../wlroots/include/wlr/types/wlr_xcursor_manager.h"
|
#include <wlr/types/wlr_xcursor_manager.h>
|
||||||
#include "../wlroots/include/wlr/types/wlr_xdg_activation_v1.h"
|
#include <wlr/types/wlr_xdg_activation_v1.h>
|
||||||
#include "../wlroots/include/wlr/types/wlr_xdg_decoration_v1.h"
|
#include <wlr/types/wlr_xdg_decoration_v1.h>
|
||||||
#include "../wlroots/include/wlr/types/wlr_xdg_output_v1.h"
|
#include <wlr/types/wlr_xdg_output_v1.h>
|
||||||
#include "../wlroots/include/wlr/types/wlr_xdg_shell.h"
|
#include <wlr/types/wlr_xdg_shell.h>
|
||||||
#include "../wlroots/include/wlr/types/wlr_subcompositor.h"
|
#include <wlr/types/wlr_subcompositor.h>
|
||||||
#include "../wlroots/include/wlr/types/wlr_scene.h"
|
#include <wlr/types/wlr_scene.h>
|
||||||
#include "../wlroots/include/wlr/types/wlr_output_damage.h"
|
#include <wlr/types/wlr_output_damage.h>
|
||||||
#include "../wlroots/include/wlr/types/wlr_input_inhibitor.h"
|
#include <wlr/types/wlr_input_inhibitor.h>
|
||||||
#include "../wlroots/include/wlr/types/wlr_keyboard_shortcuts_inhibit_v1.h"
|
#include <wlr/types/wlr_keyboard_shortcuts_inhibit_v1.h>
|
||||||
#include "../wlroots/include/wlr/types/wlr_virtual_pointer_v1.h"
|
#include <wlr/types/wlr_virtual_pointer_v1.h>
|
||||||
#include "../wlroots/include/wlr/types/wlr_foreign_toplevel_management_v1.h"
|
#include <wlr/types/wlr_foreign_toplevel_management_v1.h>
|
||||||
#include "../wlroots/include/wlr/util/log.h"
|
#include <wlr/util/log.h>
|
||||||
#include "../wlroots/include/wlr/xwayland.h"
|
#include <wlr/xwayland.h>
|
||||||
#include "../wlroots/include/wlr/util/region.h"
|
#include <wlr/util/region.h>
|
||||||
|
#include <wlr/types/wlr_tablet_pad.h>
|
||||||
|
#include <wlr/types/wlr_tablet_tool.h>
|
||||||
|
#include <wlr/types/wlr_tablet_v2.h>
|
||||||
#include <xkbcommon/xkbcommon.h>
|
#include <xkbcommon/xkbcommon.h>
|
||||||
#include <X11/Xproto.h>
|
#include <X11/Xproto.h>
|
||||||
#include "../wlroots/include/wlr/render/egl.h"
|
#include <wlr/render/egl.h>
|
||||||
#include "../wlroots/include/wlr/render/gles2.h"
|
#include <wlr/render/gles2.h>
|
||||||
#include "../wlroots/include/wlr/render/wlr_texture.h"
|
#include <wlr/render/wlr_texture.h>
|
||||||
#include "../wlroots/include/wlr/types/wlr_pointer_constraints_v1.h"
|
#include <wlr/types/wlr_pointer_constraints_v1.h>
|
||||||
#include "../wlroots/include/wlr/types/wlr_relative_pointer_v1.h"
|
#include <wlr/types/wlr_relative_pointer_v1.h>
|
||||||
|
#include <wlr/interfaces/wlr_keyboard.h>
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef class
|
#undef class
|
||||||
@@ -109,4 +113,4 @@ extern "C" {
|
|||||||
|
|
||||||
#include "helpers/Vector2D.hpp"
|
#include "helpers/Vector2D.hpp"
|
||||||
|
|
||||||
#include "../ext-workspace-unstable-v1-protocol.h"
|
#include "ext-workspace-unstable-v1-protocol.h"
|
||||||
|
@@ -482,6 +482,9 @@ void CHyprDwindleLayout::onBeginDragWindow() {
|
|||||||
void CHyprDwindleLayout::onEndDragWindow() {
|
void CHyprDwindleLayout::onEndDragWindow() {
|
||||||
const auto DRAGGINGWINDOW = g_pInputManager->currentlyDraggedWindow;
|
const auto DRAGGINGWINDOW = g_pInputManager->currentlyDraggedWindow;
|
||||||
|
|
||||||
|
if (!g_pCompositor->windowValidMapped(DRAGGINGWINDOW))
|
||||||
|
return;
|
||||||
|
|
||||||
if (DRAGGINGWINDOW->m_bDraggingTiled) {
|
if (DRAGGINGWINDOW->m_bDraggingTiled) {
|
||||||
DRAGGINGWINDOW->m_bIsFloating = false;
|
DRAGGINGWINDOW->m_bIsFloating = false;
|
||||||
changeWindowFloatingMode(DRAGGINGWINDOW);
|
changeWindowFloatingMode(DRAGGINGWINDOW);
|
||||||
@@ -494,8 +497,10 @@ void CHyprDwindleLayout::onMouseMove(const Vector2D& mousePos) {
|
|||||||
const auto DRAGGINGWINDOW = g_pInputManager->currentlyDraggedWindow;
|
const auto DRAGGINGWINDOW = g_pInputManager->currentlyDraggedWindow;
|
||||||
|
|
||||||
// Window invalid or drag begin size 0,0 meaning we rejected it.
|
// Window invalid or drag begin size 0,0 meaning we rejected it.
|
||||||
if (!g_pCompositor->windowValidMapped(DRAGGINGWINDOW) || m_vBeginDragSizeXY == Vector2D())
|
if (!g_pCompositor->windowValidMapped(DRAGGINGWINDOW) || m_vBeginDragSizeXY == Vector2D()) {
|
||||||
|
g_pInputManager->currentlyDraggedWindow = nullptr;
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const auto DELTA = Vector2D(mousePos.x - m_vBeginDragXY.x, mousePos.y - m_vBeginDragXY.y);
|
const auto DELTA = Vector2D(mousePos.x - m_vBeginDragXY.x, mousePos.y - m_vBeginDragXY.y);
|
||||||
const auto TICKDELTA = Vector2D(mousePos.x - m_vLastDragXY.x, mousePos.y - m_vLastDragXY.y);
|
const auto TICKDELTA = Vector2D(mousePos.x - m_vLastDragXY.x, mousePos.y - m_vLastDragXY.y);
|
||||||
@@ -545,11 +550,7 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, CWindow*
|
|||||||
const auto PNODE = getNodeFromWindow(PWINDOW);
|
const auto PNODE = getNodeFromWindow(PWINDOW);
|
||||||
|
|
||||||
if (!PNODE) {
|
if (!PNODE) {
|
||||||
PWINDOW->m_vRealSize.setValueAndWarp(PWINDOW->m_vRealSize.goalv() + pixResize);
|
PWINDOW->m_vRealSize = Vector2D(std::clamp((PWINDOW->m_vRealSize.goalv() + pixResize).x, (double)20, (double)999999), std::clamp((PWINDOW->m_vRealSize.goalv() + pixResize).y, (double)20, (double)999999));
|
||||||
PWINDOW->m_vRealSize.setValueAndWarp(Vector2D(std::clamp(PWINDOW->m_vRealSize.vec().x, (double)20, (double)999999), std::clamp(PWINDOW->m_vRealSize.vec().y, (double)20, (double)999999)));
|
|
||||||
|
|
||||||
g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goalv());
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -675,21 +676,24 @@ void CHyprDwindleLayout::onWindowCreatedFloating(CWindow* pWindow) {
|
|||||||
g_pCompositor->moveWindowToTop(pWindow);
|
g_pCompositor->moveWindowToTop(pWindow);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CHyprDwindleLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscreenMode fullscreenMode) {
|
void CHyprDwindleLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscreenMode fullscreenMode, bool on) {
|
||||||
if (!g_pCompositor->windowValidMapped(pWindow))
|
if (!g_pCompositor->windowValidMapped(pWindow))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (on == pWindow->m_bIsFullscreen)
|
||||||
|
return; // ignore
|
||||||
|
|
||||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID);
|
const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID);
|
||||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID);
|
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID);
|
||||||
|
|
||||||
if (PWORKSPACE->m_bHasFullscreenWindow && !pWindow->m_bIsFullscreen) {
|
if (PWORKSPACE->m_bHasFullscreenWindow && on) {
|
||||||
// if the window wants to be fullscreen but there already is one,
|
// if the window wants to be fullscreen but there already is one,
|
||||||
// ignore the request.
|
// ignore the request.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// otherwise, accept it.
|
// otherwise, accept it.
|
||||||
pWindow->m_bIsFullscreen = !pWindow->m_bIsFullscreen;
|
pWindow->m_bIsFullscreen = on;
|
||||||
PWORKSPACE->m_bHasFullscreenWindow = !PWORKSPACE->m_bHasFullscreenWindow;
|
PWORKSPACE->m_bHasFullscreenWindow = !PWORKSPACE->m_bHasFullscreenWindow;
|
||||||
|
|
||||||
if (!pWindow->m_bIsFullscreen) {
|
if (!pWindow->m_bIsFullscreen) {
|
||||||
@@ -906,6 +910,11 @@ void CHyprDwindleLayout::switchWindows(CWindow* pWindow, CWindow* pWindow2) {
|
|||||||
if (!PNODE2 || !PNODE)
|
if (!PNODE2 || !PNODE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (PNODE->workspaceID != PNODE2->workspaceID) {
|
||||||
|
Debug::log(ERR, "Dwindle: Rejecting a swap between workspaces");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// we will not delete the nodes, just fix the tree
|
// we will not delete the nodes, just fix the tree
|
||||||
if (PNODE2->pParent == PNODE->pParent) {
|
if (PNODE2->pParent == PNODE->pParent) {
|
||||||
const auto PPARENT = PNODE->pParent;
|
const auto PPARENT = PNODE->pParent;
|
||||||
@@ -993,3 +1002,19 @@ void CHyprDwindleLayout::toggleSplit(CWindow* pWindow) {
|
|||||||
std::string CHyprDwindleLayout::getLayoutName() {
|
std::string CHyprDwindleLayout::getLayoutName() {
|
||||||
return "dwindle";
|
return "dwindle";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CHyprDwindleLayout::moveActiveWindow(const Vector2D& delta, CWindow* pWindow) {
|
||||||
|
const auto PWINDOW = pWindow ? pWindow : g_pCompositor->m_pLastWindow;
|
||||||
|
|
||||||
|
if (!g_pCompositor->windowValidMapped(PWINDOW))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!PWINDOW->m_bIsFloating) {
|
||||||
|
Debug::log(LOG, "Dwindle cannot move a tiled window in moveActiveWindow!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
PWINDOW->m_vRealPosition = PWINDOW->m_vRealPosition.goalv() + delta;
|
||||||
|
|
||||||
|
g_pHyprRenderer->damageWindow(PWINDOW);
|
||||||
|
}
|
@@ -49,10 +49,11 @@ public:
|
|||||||
virtual void changeWindowFloatingMode(CWindow*);
|
virtual void changeWindowFloatingMode(CWindow*);
|
||||||
virtual void onBeginDragWindow();
|
virtual void onBeginDragWindow();
|
||||||
virtual void resizeActiveWindow(const Vector2D&, CWindow* pWindow = nullptr);
|
virtual void resizeActiveWindow(const Vector2D&, CWindow* pWindow = nullptr);
|
||||||
|
virtual void moveActiveWindow(const Vector2D&, CWindow* pWindow = nullptr);
|
||||||
virtual void onEndDragWindow();
|
virtual void onEndDragWindow();
|
||||||
virtual void onMouseMove(const Vector2D&);
|
virtual void onMouseMove(const Vector2D&);
|
||||||
virtual void onWindowCreatedFloating(CWindow*);
|
virtual void onWindowCreatedFloating(CWindow*);
|
||||||
virtual void fullscreenRequestForWindow(CWindow*, eFullscreenMode);
|
virtual void fullscreenRequestForWindow(CWindow*, eFullscreenMode, bool);
|
||||||
virtual std::any layoutMessage(SLayoutMessageHeader, std::string);
|
virtual std::any layoutMessage(SLayoutMessageHeader, std::string);
|
||||||
virtual SWindowRenderLayoutHints requestRenderHints(CWindow*);
|
virtual SWindowRenderLayoutHints requestRenderHints(CWindow*);
|
||||||
virtual void switchWindows(CWindow*, CWindow*);
|
virtual void switchWindows(CWindow*, CWindow*);
|
||||||
|
@@ -55,6 +55,12 @@ public:
|
|||||||
Optional pWindow for a specific window
|
Optional pWindow for a specific window
|
||||||
*/
|
*/
|
||||||
virtual void resizeActiveWindow(const Vector2D&, CWindow* pWindow = nullptr) = 0;
|
virtual void resizeActiveWindow(const Vector2D&, CWindow* pWindow = nullptr) = 0;
|
||||||
|
/*
|
||||||
|
Called when a user requests a move of the current window by a vec
|
||||||
|
Vector2D holds pixel values
|
||||||
|
Optional pWindow for a specific window
|
||||||
|
*/
|
||||||
|
virtual void moveActiveWindow(const Vector2D&, CWindow* pWindow = nullptr) = 0;
|
||||||
/*
|
/*
|
||||||
Called when a window is ended being dragged
|
Called when a window is ended being dragged
|
||||||
(mouse up)
|
(mouse up)
|
||||||
@@ -78,7 +84,7 @@ public:
|
|||||||
The layout sets all the fullscreen flags.
|
The layout sets all the fullscreen flags.
|
||||||
It can either accept or ignore.
|
It can either accept or ignore.
|
||||||
*/
|
*/
|
||||||
virtual void fullscreenRequestForWindow(CWindow*, eFullscreenMode) = 0;
|
virtual void fullscreenRequestForWindow(CWindow*, eFullscreenMode, bool) = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Called when a dispatcher requests a custom message
|
Called when a dispatcher requests a custom message
|
||||||
|
@@ -23,20 +23,22 @@ void CAnimationManager::tick() {
|
|||||||
|
|
||||||
bool animationsDisabled = false;
|
bool animationsDisabled = false;
|
||||||
|
|
||||||
if (!g_pConfigManager->getInt("animations:enabled"))
|
static auto *const PANIMENABLED = &g_pConfigManager->getConfigValuePtr("animations:enabled")->intValue;
|
||||||
|
|
||||||
|
if (!*PANIMENABLED)
|
||||||
animationsDisabled = true;
|
animationsDisabled = true;
|
||||||
|
|
||||||
const float ANIMSPEED = g_pConfigManager->getFloat("animations:speed");
|
static auto *const PANIMSPEED = &g_pConfigManager->getConfigValuePtr("animations:speed")->floatValue;
|
||||||
const auto BORDERSIZE = g_pConfigManager->getInt("general:border_size");
|
static auto *const PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue;
|
||||||
const auto BEZIERSTR = g_pConfigManager->getString("animations:curve");
|
static auto *const BEZIERSTR = &g_pConfigManager->getConfigValuePtr("animations:curve")->strValue;
|
||||||
|
|
||||||
auto DEFAULTBEZIER = m_mBezierCurves.find(BEZIERSTR);
|
auto DEFAULTBEZIER = m_mBezierCurves.find(*BEZIERSTR);
|
||||||
if (DEFAULTBEZIER == m_mBezierCurves.end())
|
if (DEFAULTBEZIER == m_mBezierCurves.end())
|
||||||
DEFAULTBEZIER = m_mBezierCurves.find("default");
|
DEFAULTBEZIER = m_mBezierCurves.find("default");
|
||||||
|
|
||||||
for (auto& av : m_lAnimatedVariables) {
|
for (auto& av : m_lAnimatedVariables) {
|
||||||
// get speed
|
// get speed
|
||||||
const auto SPEED = *av->m_pSpeed == 0 ? ANIMSPEED : *av->m_pSpeed;
|
const auto SPEED = *av->m_pSpeed == 0 ? *PANIMSPEED : *av->m_pSpeed;
|
||||||
|
|
||||||
// window stuff
|
// window stuff
|
||||||
const auto PWINDOW = (CWindow*)av->m_pWindow;
|
const auto PWINDOW = (CWindow*)av->m_pWindow;
|
||||||
@@ -45,7 +47,7 @@ void CAnimationManager::tick() {
|
|||||||
|
|
||||||
wlr_box WLRBOXPREV = {0,0,0,0};
|
wlr_box WLRBOXPREV = {0,0,0,0};
|
||||||
if (PWINDOW) {
|
if (PWINDOW) {
|
||||||
WLRBOXPREV = {(int)PWINDOW->m_vRealPosition.vec().x - BORDERSIZE - 1, (int)PWINDOW->m_vRealPosition.vec().y - BORDERSIZE - 1, (int)PWINDOW->m_vRealSize.vec().x + 2 * BORDERSIZE + 2, (int)PWINDOW->m_vRealSize.vec().y + 2 * BORDERSIZE + 2};
|
WLRBOXPREV = {(int)PWINDOW->m_vRealPosition.vec().x - (int)*PBORDERSIZE - 1, (int)PWINDOW->m_vRealPosition.vec().y - (int)*PBORDERSIZE - 1, (int)PWINDOW->m_vRealSize.vec().x + 2 * (int)*PBORDERSIZE + 2, (int)PWINDOW->m_vRealSize.vec().y + 2 * (int)*PBORDERSIZE + 2};
|
||||||
} else if (PWORKSPACE) {
|
} else if (PWORKSPACE) {
|
||||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(PWORKSPACE->m_iMonitorID);
|
const auto PMONITOR = g_pCompositor->getMonitorFromID(PWORKSPACE->m_iMonitorID);
|
||||||
WLRBOXPREV = {(int)PMONITOR->vecPosition.x, (int)PMONITOR->vecPosition.y, (int)PMONITOR->vecSize.x, (int)PMONITOR->vecSize.y};
|
WLRBOXPREV = {(int)PMONITOR->vecPosition.x, (int)PMONITOR->vecPosition.y, (int)PMONITOR->vecSize.x, (int)PMONITOR->vecSize.y};
|
||||||
@@ -53,21 +55,6 @@ void CAnimationManager::tick() {
|
|||||||
WLRBOXPREV = PLAYER->geometry;
|
WLRBOXPREV = PLAYER->geometry;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if it's disabled, if so, warp
|
|
||||||
if (av->m_pEnabled == 0 || animationsDisabled) {
|
|
||||||
av->warp();
|
|
||||||
g_pHyprRenderer->damageBox(&WLRBOXPREV);
|
|
||||||
|
|
||||||
if (PWINDOW) {
|
|
||||||
g_pHyprRenderer->damageWindow(PWINDOW);
|
|
||||||
// set size and pos if valid
|
|
||||||
if (g_pCompositor->windowValidMapped(PWINDOW))
|
|
||||||
g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goalv());
|
|
||||||
}
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// beziers are with a switch unforto
|
// beziers are with a switch unforto
|
||||||
// TODO: maybe do something cleaner
|
// TODO: maybe do something cleaner
|
||||||
|
|
||||||
@@ -78,6 +65,13 @@ void CAnimationManager::tick() {
|
|||||||
switch (av->m_eVarType) {
|
switch (av->m_eVarType) {
|
||||||
case AVARTYPE_FLOAT: {
|
case AVARTYPE_FLOAT: {
|
||||||
if (!deltazero(av->m_fValue, av->m_fGoal)) {
|
if (!deltazero(av->m_fValue, av->m_fGoal)) {
|
||||||
|
|
||||||
|
// for disabled anims just warp
|
||||||
|
if (av->m_pEnabled == 0 || animationsDisabled) {
|
||||||
|
av->warp();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
const auto DELTA = av->m_fGoal - av->m_fBegun;
|
const auto DELTA = av->m_fGoal - av->m_fBegun;
|
||||||
const auto BEZIER = m_mBezierCurves.find(*av->m_pBezier);
|
const auto BEZIER = m_mBezierCurves.find(*av->m_pBezier);
|
||||||
|
|
||||||
@@ -96,6 +90,13 @@ void CAnimationManager::tick() {
|
|||||||
}
|
}
|
||||||
case AVARTYPE_VECTOR: {
|
case AVARTYPE_VECTOR: {
|
||||||
if (!deltazero(av->m_vValue, av->m_vGoal)) {
|
if (!deltazero(av->m_vValue, av->m_vGoal)) {
|
||||||
|
|
||||||
|
// for disabled anims just warp
|
||||||
|
if (av->m_pEnabled == 0 || animationsDisabled) {
|
||||||
|
av->warp();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
const auto DELTA = av->m_vGoal - av->m_vBegun;
|
const auto DELTA = av->m_vGoal - av->m_vBegun;
|
||||||
const auto BEZIER = m_mBezierCurves.find(*av->m_pBezier);
|
const auto BEZIER = m_mBezierCurves.find(*av->m_pBezier);
|
||||||
|
|
||||||
@@ -114,6 +115,13 @@ void CAnimationManager::tick() {
|
|||||||
}
|
}
|
||||||
case AVARTYPE_COLOR: {
|
case AVARTYPE_COLOR: {
|
||||||
if (!deltazero(av->m_cValue, av->m_cGoal)) {
|
if (!deltazero(av->m_cValue, av->m_cGoal)) {
|
||||||
|
|
||||||
|
// for disabled anims just warp
|
||||||
|
if (av->m_pEnabled == 0 || animationsDisabled) {
|
||||||
|
av->warp();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
const auto DELTA = av->m_cGoal - av->m_cBegun;
|
const auto DELTA = av->m_cGoal - av->m_cBegun;
|
||||||
const auto BEZIER = m_mBezierCurves.find(*av->m_pBezier);
|
const auto BEZIER = m_mBezierCurves.find(*av->m_pBezier);
|
||||||
|
|
||||||
@@ -152,8 +160,9 @@ void CAnimationManager::tick() {
|
|||||||
RASSERT(PWINDOW, "Tried to AVARDAMAGE_BORDER a non-window AVAR!");
|
RASSERT(PWINDOW, "Tried to AVARDAMAGE_BORDER a non-window AVAR!");
|
||||||
|
|
||||||
// damage only the border.
|
// damage only the border.
|
||||||
const auto BORDERSIZE = g_pConfigManager->getInt("general:border_size") + 1; // +1 for padding and shit
|
static auto *const PROUNDING = &g_pConfigManager->getConfigValuePtr("decoration:rounding")->intValue;
|
||||||
const auto ROUNDINGSIZE = g_pConfigManager->getInt("decoration:rounding") + 1;
|
const auto ROUNDINGSIZE = *PROUNDING + 1;
|
||||||
|
const auto BORDERSIZE = *PBORDERSIZE;
|
||||||
|
|
||||||
// damage for old box
|
// damage for old box
|
||||||
g_pHyprRenderer->damageBox(WLRBOXPREV.x - BORDERSIZE, WLRBOXPREV.y - BORDERSIZE, WLRBOXPREV.width + 2 * BORDERSIZE, BORDERSIZE + ROUNDINGSIZE); // top
|
g_pHyprRenderer->damageBox(WLRBOXPREV.x - BORDERSIZE, WLRBOXPREV.y - BORDERSIZE, WLRBOXPREV.width + 2 * BORDERSIZE, BORDERSIZE + ROUNDINGSIZE); // top
|
||||||
|
@@ -105,6 +105,12 @@ void CEventManager::startThread() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CEventManager::postEvent(const SHyprIPCEvent event) {
|
void CEventManager::postEvent(const SHyprIPCEvent event) {
|
||||||
|
|
||||||
|
if (m_bIgnoreEvents) {
|
||||||
|
Debug::log(WARN, "Suppressed (ignoreevents true) event of type %s, content: %s",event.event.c_str(), event.data.c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
std::thread([&](const SHyprIPCEvent ev) {
|
std::thread([&](const SHyprIPCEvent ev) {
|
||||||
eventQueueMutex.lock();
|
eventQueueMutex.lock();
|
||||||
m_dQueuedEvents.push_back(ev);
|
m_dQueuedEvents.push_back(ev);
|
||||||
|
@@ -19,6 +19,8 @@ public:
|
|||||||
|
|
||||||
void startThread();
|
void startThread();
|
||||||
|
|
||||||
|
bool m_bIgnoreEvents = false;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
std::mutex eventQueueMutex;
|
std::mutex eventQueueMutex;
|
||||||
|
@@ -1,5 +1,7 @@
|
|||||||
#include "KeybindManager.hpp"
|
#include "KeybindManager.hpp"
|
||||||
|
|
||||||
|
#include <regex>
|
||||||
|
|
||||||
CKeybindManager::CKeybindManager() {
|
CKeybindManager::CKeybindManager() {
|
||||||
// initialize all dispatchers
|
// initialize all dispatchers
|
||||||
|
|
||||||
@@ -26,6 +28,10 @@ CKeybindManager::CKeybindManager() {
|
|||||||
m_mDispatchers["togglespecialworkspace"] = toggleSpecialWorkspace;
|
m_mDispatchers["togglespecialworkspace"] = toggleSpecialWorkspace;
|
||||||
m_mDispatchers["forcerendererreload"] = forceRendererReload;
|
m_mDispatchers["forcerendererreload"] = forceRendererReload;
|
||||||
m_mDispatchers["resizeactive"] = resizeActive;
|
m_mDispatchers["resizeactive"] = resizeActive;
|
||||||
|
m_mDispatchers["moveactive"] = moveActive;
|
||||||
|
m_mDispatchers["cyclenext"] = circleNext;
|
||||||
|
m_mDispatchers["focuswindowbyclass"] = focusWindowByClass;
|
||||||
|
m_mDispatchers["submap"] = setSubmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CKeybindManager::addKeybind(SKeybind kb) {
|
void CKeybindManager::addKeybind(SKeybind kb) {
|
||||||
@@ -68,13 +74,11 @@ bool CKeybindManager::handleKeybinds(const uint32_t& modmask, const xkb_keysym_t
|
|||||||
if (handleInternalKeybinds(key))
|
if (handleInternalKeybinds(key))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (g_pCompositor->m_sSeat.exclusiveClient){
|
if (g_pCompositor->m_sSeat.exclusiveClient)
|
||||||
Debug::log(LOG, "Not handling keybinds due to there being an exclusive inhibited client.");
|
Debug::log(LOG, "Keybind handling only locked (inhibitor)");
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto& k : m_lKeybinds) {
|
for (auto& k : m_lKeybinds) {
|
||||||
if (modmask != k.modmask)
|
if (modmask != k.modmask || (g_pCompositor->m_sSeat.exclusiveClient && !k.locked) || k.submap != m_szCurrentSelectedSubmap)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// oMg such performance hit!!11!
|
// oMg such performance hit!!11!
|
||||||
@@ -137,11 +141,48 @@ void CKeybindManager::spawn(std::string args) {
|
|||||||
args = "WAYLAND_DISPLAY=" + std::string(g_pCompositor->m_szWLDisplaySocket) + " " + args;
|
args = "WAYLAND_DISPLAY=" + std::string(g_pCompositor->m_szWLDisplaySocket) + " " + args;
|
||||||
|
|
||||||
Debug::log(LOG, "Executing %s", args.c_str());
|
Debug::log(LOG, "Executing %s", args.c_str());
|
||||||
if (fork() == 0) {
|
|
||||||
execl("/bin/sh", "/bin/sh", "-c", args.c_str(), nullptr);
|
|
||||||
|
|
||||||
|
int socket[2];
|
||||||
|
if (pipe(socket) != 0) {
|
||||||
|
Debug::log(LOG, "Unable to create pipe for fork");
|
||||||
|
}
|
||||||
|
|
||||||
|
pid_t child, grandchild;
|
||||||
|
child = fork();
|
||||||
|
if (child < 0) {
|
||||||
|
close(socket[0]);
|
||||||
|
close(socket[1]);
|
||||||
|
Debug::log(LOG, "Fail to create the first fork");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (child == 0) {
|
||||||
|
// run in child
|
||||||
|
grandchild = fork();
|
||||||
|
if (grandchild == 0) {
|
||||||
|
// run in grandchild
|
||||||
|
close(socket[0]);
|
||||||
|
close(socket[1]);
|
||||||
|
execl("/bin/sh", "/bin/sh", "-c", args.c_str(), nullptr);
|
||||||
|
// exit grandchild
|
||||||
_exit(0);
|
_exit(0);
|
||||||
}
|
}
|
||||||
|
close(socket[0]);
|
||||||
|
write(socket[1], &grandchild, sizeof(grandchild));
|
||||||
|
close(socket[1]);
|
||||||
|
// exit child
|
||||||
|
_exit(0);
|
||||||
|
}
|
||||||
|
// run in parent
|
||||||
|
close(socket[1]);
|
||||||
|
read(socket[0], &grandchild, sizeof(grandchild));
|
||||||
|
close(socket[0]);
|
||||||
|
// clear child and leave child to init
|
||||||
|
waitpid(child, NULL, 0);
|
||||||
|
if (child < 0) {
|
||||||
|
Debug::log(LOG, "Fail to create the second fork");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Debug::log(LOG, "Process Created with pid %d", grandchild);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CKeybindManager::killActive(std::string args) {
|
void CKeybindManager::killActive(std::string args) {
|
||||||
@@ -239,8 +280,6 @@ void CKeybindManager::changeworkspace(std::string args) {
|
|||||||
// start anim on new workspace
|
// start anim on new workspace
|
||||||
PWORKSPACETOCHANGETO->startAnim(true, ANIMTOLEFT);
|
PWORKSPACETOCHANGETO->startAnim(true, ANIMTOLEFT);
|
||||||
|
|
||||||
// Event ONLY if workspace is actually "changed" and we arent just focusing
|
|
||||||
if (!m_bSuppressWorkspaceChangeEvents)
|
|
||||||
g_pEventManager->postEvent(SHyprIPCEvent("workspace", PWORKSPACETOCHANGETO->m_szName));
|
g_pEventManager->postEvent(SHyprIPCEvent("workspace", PWORKSPACETOCHANGETO->m_szName));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -250,9 +289,6 @@ void CKeybindManager::changeworkspace(std::string args) {
|
|||||||
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr, middle.x, middle.y);
|
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr, middle.x, middle.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
// focus the first window
|
|
||||||
g_pCompositor->focusWindow(g_pCompositor->getFirstWindowOnWorkspace(workspaceToChangeTo));
|
|
||||||
|
|
||||||
// set active and deactivate all other in wlr
|
// set active and deactivate all other in wlr
|
||||||
g_pCompositor->deactivateAllWLRWorkspaces(PWORKSPACETOCHANGETO->m_pWlrHandle);
|
g_pCompositor->deactivateAllWLRWorkspaces(PWORKSPACETOCHANGETO->m_pWlrHandle);
|
||||||
PWORKSPACETOCHANGETO->setActive(true);
|
PWORKSPACETOCHANGETO->setActive(true);
|
||||||
@@ -319,7 +355,6 @@ void CKeybindManager::changeworkspace(std::string args) {
|
|||||||
g_pInputManager->refocus();
|
g_pInputManager->refocus();
|
||||||
|
|
||||||
// Event
|
// Event
|
||||||
if (!m_bSuppressWorkspaceChangeEvents)
|
|
||||||
g_pEventManager->postEvent(SHyprIPCEvent("workspace", PWORKSPACE->m_szName));
|
g_pEventManager->postEvent(SHyprIPCEvent("workspace", PWORKSPACE->m_szName));
|
||||||
|
|
||||||
Debug::log(LOG, "Changed to workspace %i", workspaceToChangeTo);
|
Debug::log(LOG, "Changed to workspace %i", workspaceToChangeTo);
|
||||||
@@ -331,15 +366,7 @@ void CKeybindManager::fullscreenActive(std::string args) {
|
|||||||
if (!g_pCompositor->windowValidMapped(PWINDOW))
|
if (!g_pCompositor->windowValidMapped(PWINDOW))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
g_pLayoutManager->getCurrentLayout()->fullscreenRequestForWindow(PWINDOW, args == "1" ? eFullscreenMode::FULLSCREEN_MAXIMIZED : eFullscreenMode::FULLSCREEN_FULL);
|
g_pCompositor->setWindowFullscreen(PWINDOW, !PWINDOW->m_bIsFullscreen, args == "1" ? FULLSCREEN_MAXIMIZED : FULLSCREEN_FULL);
|
||||||
|
|
||||||
g_pXWaylandManager->setWindowFullscreen(PWINDOW, PWINDOW->m_bIsFullscreen && args == "0");
|
|
||||||
|
|
||||||
// make all windows on the same workspace under the fullscreen window
|
|
||||||
for (auto& w : g_pCompositor->m_lWindows) {
|
|
||||||
if (w.m_iWorkspaceID == PWINDOW->m_iWorkspaceID)
|
|
||||||
w.m_bCreatedOverFullscreen = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CKeybindManager::moveActiveToWorkspace(std::string args) {
|
void CKeybindManager::moveActiveToWorkspace(std::string args) {
|
||||||
@@ -413,6 +440,8 @@ void CKeybindManager::moveActiveToWorkspace(std::string args) {
|
|||||||
for (auto& m : g_pCompositor->m_lMonitors)
|
for (auto& m : g_pCompositor->m_lMonitors)
|
||||||
m.specialWorkspaceOpen = false;
|
m.specialWorkspaceOpen = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
g_pInputManager->refocus();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CKeybindManager::moveActiveToWorkspaceSilent(std::string args) {
|
void CKeybindManager::moveActiveToWorkspaceSilent(std::string args) {
|
||||||
@@ -449,7 +478,7 @@ void CKeybindManager::moveActiveToWorkspaceSilent(std::string args) {
|
|||||||
const auto POLDWORKSPACEONMON = g_pCompositor->getWorkspaceByID(OLDWORKSPACEIDONMONITOR);
|
const auto POLDWORKSPACEONMON = g_pCompositor->getWorkspaceByID(OLDWORKSPACEIDONMONITOR);
|
||||||
const auto POLDWORKSPACEIDRETURN = g_pCompositor->getWorkspaceByID(OLDWORKSPACEIDRETURN);
|
const auto POLDWORKSPACEIDRETURN = g_pCompositor->getWorkspaceByID(OLDWORKSPACEIDRETURN);
|
||||||
|
|
||||||
m_bSuppressWorkspaceChangeEvents = true;
|
g_pEventManager->m_bIgnoreEvents = true;
|
||||||
|
|
||||||
moveActiveToWorkspace(args);
|
moveActiveToWorkspace(args);
|
||||||
|
|
||||||
@@ -468,7 +497,9 @@ void CKeybindManager::moveActiveToWorkspaceSilent(std::string args) {
|
|||||||
POLDWORKSPACEONMON->m_vRenderOffset.setValueAndWarp(Vector2D(0, 0));
|
POLDWORKSPACEONMON->m_vRenderOffset.setValueAndWarp(Vector2D(0, 0));
|
||||||
POLDWORKSPACEONMON->m_fAlpha.setValueAndWarp(255.f);
|
POLDWORKSPACEONMON->m_fAlpha.setValueAndWarp(255.f);
|
||||||
|
|
||||||
m_bSuppressWorkspaceChangeEvents = false;
|
g_pEventManager->m_bIgnoreEvents = false;
|
||||||
|
|
||||||
|
g_pInputManager->refocus();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CKeybindManager::moveFocusTo(std::string args) {
|
void CKeybindManager::moveFocusTo(std::string args) {
|
||||||
@@ -855,6 +886,37 @@ void CKeybindManager::resizeActive(std::string args) {
|
|||||||
std::string x = args.substr(0, args.find_first_of(' '));
|
std::string x = args.substr(0, args.find_first_of(' '));
|
||||||
std::string y = args.substr(args.find_first_of(' ') + 1);
|
std::string y = args.substr(args.find_first_of(' ') + 1);
|
||||||
|
|
||||||
|
if (x == "exact") {
|
||||||
|
std::string newX = y.substr(0, y.find_first_of(' '));
|
||||||
|
std::string newY = y.substr(y.find_first_of(' ') + 1);
|
||||||
|
|
||||||
|
if (!isNumber(newX) || !isNumber(newY)) {
|
||||||
|
Debug::log(ERR, "resizeTiledWindow: exact args not numbers");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const int X = std::stoi(newX);
|
||||||
|
const int Y = std::stoi(newY);
|
||||||
|
|
||||||
|
if (X < 10 || Y < 10) {
|
||||||
|
Debug::log(ERR, "resizeTiledWindow: exact args cannot be < 10");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// calc the delta
|
||||||
|
if (!g_pCompositor->windowValidMapped(g_pCompositor->m_pLastWindow))
|
||||||
|
return; // ignore
|
||||||
|
|
||||||
|
const auto PWINDOW = g_pCompositor->m_pLastWindow;
|
||||||
|
|
||||||
|
const int DX = X - PWINDOW->m_vRealSize.goalv().x;
|
||||||
|
const int DY = Y - PWINDOW->m_vRealSize.goalv().y;
|
||||||
|
|
||||||
|
g_pLayoutManager->getCurrentLayout()->resizeActiveWindow(Vector2D(DX, DY));
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!isNumber(x) || !isNumber(y)) {
|
if (!isNumber(x) || !isNumber(y)) {
|
||||||
Debug::log(ERR, "resizeTiledWindow: args not numbers");
|
Debug::log(ERR, "resizeTiledWindow: args not numbers");
|
||||||
return;
|
return;
|
||||||
@@ -865,3 +927,107 @@ void CKeybindManager::resizeActive(std::string args) {
|
|||||||
|
|
||||||
g_pLayoutManager->getCurrentLayout()->resizeActiveWindow(Vector2D(X, Y));
|
g_pLayoutManager->getCurrentLayout()->resizeActiveWindow(Vector2D(X, Y));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CKeybindManager::moveActive(std::string args) {
|
||||||
|
if (args.find_first_of(' ') == std::string::npos)
|
||||||
|
return;
|
||||||
|
|
||||||
|
std::string x = args.substr(0, args.find_first_of(' '));
|
||||||
|
std::string y = args.substr(args.find_first_of(' ') + 1);
|
||||||
|
|
||||||
|
if (x == "exact") {
|
||||||
|
std::string newX = y.substr(0, y.find_first_of(' '));
|
||||||
|
std::string newY = y.substr(y.find_first_of(' ') + 1);
|
||||||
|
|
||||||
|
if (!isNumber(newX) || !isNumber(newY)) {
|
||||||
|
Debug::log(ERR, "moveActive: exact args not numbers");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const int X = std::stoi(newX);
|
||||||
|
const int Y = std::stoi(newY);
|
||||||
|
|
||||||
|
if (X < 0 || Y < 0) {
|
||||||
|
Debug::log(ERR, "moveActive: exact args cannot be < 0");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// calc the delta
|
||||||
|
if (!g_pCompositor->windowValidMapped(g_pCompositor->m_pLastWindow))
|
||||||
|
return; // ignore
|
||||||
|
|
||||||
|
const auto PWINDOW = g_pCompositor->m_pLastWindow;
|
||||||
|
|
||||||
|
const int DX = X - PWINDOW->m_vRealPosition.goalv().x;
|
||||||
|
const int DY = Y - PWINDOW->m_vRealPosition.goalv().y;
|
||||||
|
|
||||||
|
g_pLayoutManager->getCurrentLayout()->moveActiveWindow(Vector2D(DX, DY));
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isNumber(x) || !isNumber(y)) {
|
||||||
|
Debug::log(ERR, "moveActive: args not numbers");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const int X = std::stoi(x);
|
||||||
|
const int Y = std::stoi(y);
|
||||||
|
|
||||||
|
g_pLayoutManager->getCurrentLayout()->moveActiveWindow(Vector2D(X, Y));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CKeybindManager::circleNext(std::string) {
|
||||||
|
if (!g_pCompositor->windowValidMapped(g_pCompositor->m_pLastWindow))
|
||||||
|
return;
|
||||||
|
|
||||||
|
g_pCompositor->focusWindow(g_pCompositor->getNextWindowOnWorkspace(g_pCompositor->m_pLastWindow));
|
||||||
|
|
||||||
|
const auto MIDPOINT = g_pCompositor->m_pLastWindow->m_vRealPosition.goalv() + g_pCompositor->m_pLastWindow->m_vRealSize.goalv() / 2.f;
|
||||||
|
|
||||||
|
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr, MIDPOINT.x, MIDPOINT.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CKeybindManager::focusWindowByClass(std::string clazz) {
|
||||||
|
std::regex classCheck(clazz);
|
||||||
|
|
||||||
|
for (auto& w : g_pCompositor->m_lWindows) {
|
||||||
|
if (!w.m_bIsMapped || w.m_bHidden)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const auto windowClass = g_pXWaylandManager->getAppIDClass(&w);
|
||||||
|
|
||||||
|
if (!std::regex_search(windowClass, classCheck))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Debug::log(LOG, "Focusing to window name: %s", w.m_szTitle.c_str());
|
||||||
|
|
||||||
|
changeworkspace(std::to_string(w.m_iWorkspaceID));
|
||||||
|
|
||||||
|
g_pCompositor->focusWindow(&w);
|
||||||
|
|
||||||
|
const auto MIDPOINT = w.m_vRealPosition.goalv() + w.m_vRealSize.goalv() / 2.f;
|
||||||
|
|
||||||
|
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr, MIDPOINT.x, MIDPOINT.y);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CKeybindManager::setSubmap(std::string submap) {
|
||||||
|
if (submap == "reset" || submap == "") {
|
||||||
|
m_szCurrentSelectedSubmap = "";
|
||||||
|
Debug::log(LOG, "Reset active submap to the default one.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& k : g_pKeybindManager->m_lKeybinds) {
|
||||||
|
if (k.submap == submap) {
|
||||||
|
m_szCurrentSelectedSubmap = submap;
|
||||||
|
Debug::log(LOG, "Changed keybind submap to %s", submap.c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Debug::log(ERR, "Cannot set submap %s, submap doesn't exist (wasn't registered!)", submap.c_str());
|
||||||
|
}
|
||||||
|
@@ -11,6 +11,8 @@ struct SKeybind {
|
|||||||
uint32_t modmask = 0;
|
uint32_t modmask = 0;
|
||||||
std::string handler = "";
|
std::string handler = "";
|
||||||
std::string arg = "";
|
std::string arg = "";
|
||||||
|
bool locked = false;
|
||||||
|
std::string submap = "";
|
||||||
};
|
};
|
||||||
|
|
||||||
class CKeybindManager {
|
class CKeybindManager {
|
||||||
@@ -28,9 +30,9 @@ public:
|
|||||||
private:
|
private:
|
||||||
std::list<SKeybind> m_lKeybinds;
|
std::list<SKeybind> m_lKeybinds;
|
||||||
|
|
||||||
bool handleInternalKeybinds(xkb_keysym_t);
|
inline static std::string m_szCurrentSelectedSubmap = "";
|
||||||
|
|
||||||
inline static bool m_bSuppressWorkspaceChangeEvents = false;
|
bool handleInternalKeybinds(xkb_keysym_t);
|
||||||
|
|
||||||
// -------------- Dispatchers -------------- //
|
// -------------- Dispatchers -------------- //
|
||||||
static void killActive(std::string);
|
static void killActive(std::string);
|
||||||
@@ -56,6 +58,10 @@ private:
|
|||||||
static void toggleSpecialWorkspace(std::string);
|
static void toggleSpecialWorkspace(std::string);
|
||||||
static void forceRendererReload(std::string);
|
static void forceRendererReload(std::string);
|
||||||
static void resizeActive(std::string);
|
static void resizeActive(std::string);
|
||||||
|
static void moveActive(std::string);
|
||||||
|
static void circleNext(std::string);
|
||||||
|
static void focusWindowByClass(std::string);
|
||||||
|
static void setSubmap(std::string);
|
||||||
|
|
||||||
friend class CCompositor;
|
friend class CCompositor;
|
||||||
};
|
};
|
||||||
|
@@ -124,14 +124,8 @@ void CHyprXWaylandManager::sendCloseWindow(CWindow* pWindow) {
|
|||||||
void CHyprXWaylandManager::setWindowSize(CWindow* pWindow, const Vector2D& size) {
|
void CHyprXWaylandManager::setWindowSize(CWindow* pWindow, const Vector2D& size) {
|
||||||
if (pWindow->m_bIsX11)
|
if (pWindow->m_bIsX11)
|
||||||
wlr_xwayland_surface_configure(pWindow->m_uSurface.xwayland, pWindow->m_vRealPosition.vec().x, pWindow->m_vRealPosition.vec().y, size.x, size.y);
|
wlr_xwayland_surface_configure(pWindow->m_uSurface.xwayland, pWindow->m_vRealPosition.vec().x, pWindow->m_vRealPosition.vec().y, size.x, size.y);
|
||||||
else {
|
else
|
||||||
// I don't know if this is fucking correct, but the fucking idea of putting shadows into a window's surface is borderline criminal.
|
wlr_xdg_toplevel_set_size(pWindow->m_uSurface.xdg->toplevel, size.x, size.y);
|
||||||
|
|
||||||
const auto XDELTA = pWindow->m_uSurface.xdg->current.geometry.width && pWindow->m_uSurface.xdg->current.geometry.height ? pWindow->m_uSurface.xdg->surface->current.width - pWindow->m_uSurface.xdg->current.geometry.width : 0;
|
|
||||||
const auto YDELTA = pWindow->m_uSurface.xdg->current.geometry.width && pWindow->m_uSurface.xdg->current.geometry.height ? pWindow->m_uSurface.xdg->surface->current.height - pWindow->m_uSurface.xdg->current.geometry.height : 0;
|
|
||||||
|
|
||||||
wlr_xdg_toplevel_set_size(pWindow->m_uSurface.xdg->toplevel, size.x - XDELTA, size.y - YDELTA);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CHyprXWaylandManager::setWindowStyleTiled(CWindow* pWindow, uint32_t edgez) {
|
void CHyprXWaylandManager::setWindowStyleTiled(CWindow* pWindow, uint32_t edgez) {
|
||||||
@@ -152,8 +146,10 @@ bool CHyprXWaylandManager::shouldBeFloated(CWindow* pWindow) {
|
|||||||
if (pWindow->m_uSurface.xwayland->window_type[i] == HYPRATOMS["_NET_WM_WINDOW_TYPE_DIALOG"] || pWindow->m_uSurface.xwayland->window_type[i] == HYPRATOMS["_NET_WM_WINDOW_TYPE_SPLASH"] ||
|
if (pWindow->m_uSurface.xwayland->window_type[i] == HYPRATOMS["_NET_WM_WINDOW_TYPE_DIALOG"] || pWindow->m_uSurface.xwayland->window_type[i] == HYPRATOMS["_NET_WM_WINDOW_TYPE_SPLASH"] ||
|
||||||
pWindow->m_uSurface.xwayland->window_type[i] == HYPRATOMS["_NET_WM_WINDOW_TYPE_TOOLBAR"] || pWindow->m_uSurface.xwayland->window_type[i] == HYPRATOMS["_NET_WM_WINDOW_TYPE_UTILITY"] ||
|
pWindow->m_uSurface.xwayland->window_type[i] == HYPRATOMS["_NET_WM_WINDOW_TYPE_TOOLBAR"] || pWindow->m_uSurface.xwayland->window_type[i] == HYPRATOMS["_NET_WM_WINDOW_TYPE_UTILITY"] ||
|
||||||
pWindow->m_uSurface.xwayland->window_type[i] == HYPRATOMS["_NET_WM_WINDOW_TYPE_TOOLTIP"] || pWindow->m_uSurface.xwayland->window_type[i] == HYPRATOMS["_NET_WM_WINDOW_TYPE_POPUP_MENU"] ||
|
pWindow->m_uSurface.xwayland->window_type[i] == HYPRATOMS["_NET_WM_WINDOW_TYPE_TOOLTIP"] || pWindow->m_uSurface.xwayland->window_type[i] == HYPRATOMS["_NET_WM_WINDOW_TYPE_POPUP_MENU"] ||
|
||||||
pWindow->m_uSurface.xwayland->window_type[i] == HYPRATOMS["_NET_WM_WINDOW_TYPE_DOCK"] || pWindow->m_uSurface.xwayland->window_type[i] == HYPRATOMS["_NET_WM_WINDOW_TYPE_DROPDOWN_MENU"])
|
pWindow->m_uSurface.xwayland->window_type[i] == HYPRATOMS["_NET_WM_WINDOW_TYPE_DOCK"] || pWindow->m_uSurface.xwayland->window_type[i] == HYPRATOMS["_NET_WM_WINDOW_TYPE_DROPDOWN_MENU"] ||
|
||||||
|
pWindow->m_uSurface.xwayland->window_type[i] == HYPRATOMS["_NET_WM_WINDOW_TYPE_MENU"])
|
||||||
{
|
{
|
||||||
|
pWindow->m_bNoInitialFocus = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,8 +1,7 @@
|
|||||||
#include "InputManager.hpp"
|
#include "InputManager.hpp"
|
||||||
#include "../Compositor.hpp"
|
#include "../../Compositor.hpp"
|
||||||
|
|
||||||
void CInputManager::onMouseMoved(wlr_pointer_motion_event* e) {
|
void CInputManager::onMouseMoved(wlr_pointer_motion_event* e) {
|
||||||
|
|
||||||
float sensitivity = g_pConfigManager->getFloat("general:sensitivity");
|
float sensitivity = g_pConfigManager->getFloat("general:sensitivity");
|
||||||
|
|
||||||
const auto DELTA = g_pConfigManager->getInt("input:force_no_accel") == 1 ? Vector2D(e->unaccel_dx, e->unaccel_dy) : Vector2D(e->delta_x, e->delta_y);
|
const auto DELTA = g_pConfigManager->getInt("input:force_no_accel") == 1 ? Vector2D(e->unaccel_dx, e->unaccel_dy) : Vector2D(e->delta_x, e->delta_y);
|
||||||
@@ -15,12 +14,16 @@ void CInputManager::onMouseMoved(wlr_pointer_motion_event* e) {
|
|||||||
wlr_cursor_move(g_pCompositor->m_sWLRCursor, &e->pointer->base, DELTA.x * sensitivity, DELTA.y * sensitivity);
|
wlr_cursor_move(g_pCompositor->m_sWLRCursor, &e->pointer->base, DELTA.x * sensitivity, DELTA.y * sensitivity);
|
||||||
|
|
||||||
mouseMoveUnified(e->time_msec);
|
mouseMoveUnified(e->time_msec);
|
||||||
|
|
||||||
|
m_tmrLastCursorMovement.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CInputManager::onMouseWarp(wlr_pointer_motion_absolute_event* e) {
|
void CInputManager::onMouseWarp(wlr_pointer_motion_absolute_event* e) {
|
||||||
wlr_cursor_warp_absolute(g_pCompositor->m_sWLRCursor, &e->pointer->base, e->x, e->y);
|
wlr_cursor_warp_absolute(g_pCompositor->m_sWLRCursor, &e->pointer->base, e->x, e->y);
|
||||||
|
|
||||||
mouseMoveUnified(e->time_msec);
|
mouseMoveUnified(e->time_msec);
|
||||||
|
|
||||||
|
m_tmrLastCursorMovement.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
||||||
@@ -36,6 +39,8 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
|||||||
Vector2D mouseCoords = getMouseCoordsInternal();
|
Vector2D mouseCoords = getMouseCoordsInternal();
|
||||||
const auto PMONITOR = g_pCompositor->getMonitorFromCursor();
|
const auto PMONITOR = g_pCompositor->getMonitorFromCursor();
|
||||||
|
|
||||||
|
bool didConstraintOnCursor = false;
|
||||||
|
|
||||||
// constraints
|
// constraints
|
||||||
// All constraints TODO: multiple mice?
|
// All constraints TODO: multiple mice?
|
||||||
if (g_pCompositor->m_sSeat.mouse->currentConstraint) {
|
if (g_pCompositor->m_sSeat.mouse->currentConstraint) {
|
||||||
@@ -51,23 +56,25 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
|||||||
const auto CONSTRAINTPOS = CONSTRAINTWINDOW->m_bIsX11 ? Vector2D(CONSTRAINTWINDOW->m_uSurface.xwayland->x, CONSTRAINTWINDOW->m_uSurface.xwayland->y) : CONSTRAINTWINDOW->m_vRealPosition.vec();
|
const auto CONSTRAINTPOS = CONSTRAINTWINDOW->m_bIsX11 ? Vector2D(CONSTRAINTWINDOW->m_uSurface.xwayland->x, CONSTRAINTWINDOW->m_uSurface.xwayland->y) : CONSTRAINTWINDOW->m_vRealPosition.vec();
|
||||||
const auto CONSTRAINTSIZE = CONSTRAINTWINDOW->m_bIsX11 ? Vector2D(CONSTRAINTWINDOW->m_uSurface.xwayland->width, CONSTRAINTWINDOW->m_uSurface.xwayland->height) : CONSTRAINTWINDOW->m_vRealSize.vec();
|
const auto CONSTRAINTSIZE = CONSTRAINTWINDOW->m_bIsX11 ? Vector2D(CONSTRAINTWINDOW->m_uSurface.xwayland->width, CONSTRAINTWINDOW->m_uSurface.xwayland->height) : CONSTRAINTWINDOW->m_vRealSize.vec();
|
||||||
|
|
||||||
if (!VECINRECT(mouseCoords, CONSTRAINTPOS.x, CONSTRAINTPOS.y, CONSTRAINTPOS.x + CONSTRAINTSIZE.x, CONSTRAINTPOS.y + CONSTRAINTSIZE.y)) {
|
if (!VECINRECT(mouseCoords, CONSTRAINTPOS.x, CONSTRAINTPOS.y, CONSTRAINTPOS.x + CONSTRAINTSIZE.x - 1.0, CONSTRAINTPOS.y + CONSTRAINTSIZE.y - 1.0)) {
|
||||||
if (g_pCompositor->m_sSeat.mouse->constraintActive) {
|
if (g_pCompositor->m_sSeat.mouse->constraintActive) {
|
||||||
Vector2D deltaToFit;
|
Vector2D newConstrainedCoords = mouseCoords;
|
||||||
|
|
||||||
if (mouseCoords.x < CONSTRAINTPOS.x)
|
if (mouseCoords.x < CONSTRAINTPOS.x)
|
||||||
deltaToFit.x = CONSTRAINTPOS.x - mouseCoords.x;
|
newConstrainedCoords.x = CONSTRAINTPOS.x;
|
||||||
else if (mouseCoords.x > CONSTRAINTPOS.x + CONSTRAINTSIZE.x)
|
else if (mouseCoords.x >= CONSTRAINTPOS.x + CONSTRAINTSIZE.x)
|
||||||
deltaToFit.x = CONSTRAINTPOS.x + CONSTRAINTSIZE.x - mouseCoords.x;
|
newConstrainedCoords.x = CONSTRAINTPOS.x + CONSTRAINTSIZE.x - 1.0;
|
||||||
|
|
||||||
if (mouseCoords.y < CONSTRAINTPOS.y)
|
if (mouseCoords.y < CONSTRAINTPOS.y)
|
||||||
deltaToFit.y = CONSTRAINTPOS.y - mouseCoords.y;
|
newConstrainedCoords.y = CONSTRAINTPOS.y;
|
||||||
else if (mouseCoords.y > CONSTRAINTPOS.y + CONSTRAINTSIZE.y)
|
else if (mouseCoords.y >= CONSTRAINTPOS.y + CONSTRAINTSIZE.y)
|
||||||
deltaToFit.y = CONSTRAINTPOS.y + CONSTRAINTSIZE.y - mouseCoords.y;
|
newConstrainedCoords.y = CONSTRAINTPOS.y + CONSTRAINTSIZE.y - 1.0;
|
||||||
|
|
||||||
wlr_cursor_move(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sSeat.mouse->mouse, deltaToFit.x, deltaToFit.y);
|
wlr_cursor_warp_closest(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sSeat.mouse->mouse, newConstrainedCoords.x, newConstrainedCoords.y);
|
||||||
|
|
||||||
mouseCoords = mouseCoords + deltaToFit;
|
mouseCoords = newConstrainedCoords;
|
||||||
|
|
||||||
|
didConstraintOnCursor = true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if ((!CONSTRAINTWINDOW->m_bIsX11 && PMONITOR && CONSTRAINTWINDOW->m_iWorkspaceID == PMONITOR->activeWorkspace) || (CONSTRAINTWINDOW->m_bIsX11)) {
|
if ((!CONSTRAINTWINDOW->m_bIsX11 && PMONITOR && CONSTRAINTWINDOW->m_iWorkspaceID == PMONITOR->activeWorkspace) || (CONSTRAINTWINDOW->m_bIsX11)) {
|
||||||
@@ -85,6 +92,9 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
|||||||
// focus
|
// focus
|
||||||
wlr_surface* foundSurface = nullptr;
|
wlr_surface* foundSurface = nullptr;
|
||||||
|
|
||||||
|
if (didConstraintOnCursor)
|
||||||
|
return; // don't process when cursor constrained
|
||||||
|
|
||||||
if (PMONITOR && PMONITOR != g_pCompositor->m_pLastMonitor) {
|
if (PMONITOR && PMONITOR != g_pCompositor->m_pLastMonitor) {
|
||||||
g_pCompositor->m_pLastMonitor = PMONITOR;
|
g_pCompositor->m_pLastMonitor = PMONITOR;
|
||||||
|
|
||||||
@@ -153,7 +163,6 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
|||||||
if (!foundSurface)
|
if (!foundSurface)
|
||||||
foundSurface = g_pCompositor->vectorToLayerSurface(mouseCoords, &PMONITOR->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND], &surfaceCoords);
|
foundSurface = g_pCompositor->vectorToLayerSurface(mouseCoords, &PMONITOR->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND], &surfaceCoords);
|
||||||
|
|
||||||
|
|
||||||
if (!foundSurface) {
|
if (!foundSurface) {
|
||||||
wlr_xcursor_manager_set_cursor_image(g_pCompositor->m_sWLRXCursorMgr, "left_ptr", g_pCompositor->m_sWLRCursor);
|
wlr_xcursor_manager_set_cursor_image(g_pCompositor->m_sWLRXCursorMgr, "left_ptr", g_pCompositor->m_sWLRCursor);
|
||||||
|
|
||||||
@@ -167,20 +176,30 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
|||||||
|
|
||||||
Vector2D surfaceLocal = surfacePos == Vector2D(-1337, -1337) ? surfaceCoords : mouseCoords - surfacePos;
|
Vector2D surfaceLocal = surfacePos == Vector2D(-1337, -1337) ? surfaceCoords : mouseCoords - surfacePos;
|
||||||
|
|
||||||
|
if (pFoundWindow && !pFoundWindow->m_bIsX11 && surfacePos != Vector2D(-1337, -1337)) {
|
||||||
|
// calc for oversized windows... fucking bullshit.
|
||||||
|
wlr_box geom;
|
||||||
|
wlr_xdg_surface_get_geometry(pFoundWindow->m_uSurface.xdg, &geom);
|
||||||
|
|
||||||
|
surfaceLocal = mouseCoords - surfacePos + Vector2D(geom.x, geom.y);
|
||||||
|
}
|
||||||
|
|
||||||
if (pFoundWindow) {
|
if (pFoundWindow) {
|
||||||
if (g_pConfigManager->getInt("input:follow_mouse") == 0 && !refocus) {
|
static auto *const PFOLLOWMOUSE = &g_pConfigManager->getConfigValuePtr("input:follow_mouse")->intValue;
|
||||||
|
if (*PFOLLOWMOUSE != 1 && !refocus) {
|
||||||
if (pFoundWindow != g_pCompositor->m_pLastWindow && g_pCompositor->windowValidMapped(g_pCompositor->m_pLastWindow) && (g_pCompositor->m_pLastWindow->m_bIsFloating != pFoundWindow->m_bIsFloating)) {
|
if (pFoundWindow != g_pCompositor->m_pLastWindow && g_pCompositor->windowValidMapped(g_pCompositor->m_pLastWindow) && (g_pCompositor->m_pLastWindow->m_bIsFloating != pFoundWindow->m_bIsFloating)) {
|
||||||
// enter if change floating style
|
// enter if change floating style
|
||||||
g_pCompositor->focusWindow(pFoundWindow, foundSurface);
|
g_pCompositor->focusWindow(pFoundWindow, foundSurface);
|
||||||
wlr_seat_pointer_notify_enter(g_pCompositor->m_sSeat.seat, foundSurface, surfaceLocal.x, surfaceLocal.y);
|
wlr_seat_pointer_notify_enter(g_pCompositor->m_sSeat.seat, foundSurface, surfaceLocal.x, surfaceLocal.y);
|
||||||
|
} else if (*PFOLLOWMOUSE == 2) {
|
||||||
|
wlr_seat_pointer_notify_enter(g_pCompositor->m_sSeat.seat, foundSurface, surfaceLocal.x, surfaceLocal.y);
|
||||||
}
|
}
|
||||||
wlr_seat_pointer_notify_motion(g_pCompositor->m_sSeat.seat, time, surfaceLocal.x, surfaceLocal.y);
|
wlr_seat_pointer_notify_motion(g_pCompositor->m_sSeat.seat, time, surfaceLocal.x, surfaceLocal.y);
|
||||||
return; // don't enter any new surfaces
|
return; // don't enter any new surfaces
|
||||||
} else {
|
} else {
|
||||||
g_pCompositor->focusWindow(pFoundWindow, foundSurface);
|
g_pCompositor->focusWindow(pFoundWindow, foundSurface);
|
||||||
}
|
}
|
||||||
}
|
} else
|
||||||
else
|
|
||||||
g_pCompositor->focusSurface(foundSurface);
|
g_pCompositor->focusSurface(foundSurface);
|
||||||
|
|
||||||
wlr_seat_pointer_notify_enter(g_pCompositor->m_sSeat.seat, foundSurface, surfaceLocal.x, surfaceLocal.y);
|
wlr_seat_pointer_notify_enter(g_pCompositor->m_sSeat.seat, foundSurface, surfaceLocal.x, surfaceLocal.y);
|
||||||
@@ -190,8 +209,15 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
|||||||
void CInputManager::onMouseButton(wlr_pointer_button_event* e) {
|
void CInputManager::onMouseButton(wlr_pointer_button_event* e) {
|
||||||
wlr_idle_notify_activity(g_pCompositor->m_sWLRIdle, g_pCompositor->m_sSeat.seat);
|
wlr_idle_notify_activity(g_pCompositor->m_sWLRIdle, g_pCompositor->m_sSeat.seat);
|
||||||
|
|
||||||
|
m_tmrLastCursorMovement.reset();
|
||||||
|
|
||||||
const auto PKEYBOARD = wlr_seat_get_keyboard(g_pCompositor->m_sSeat.seat);
|
const auto PKEYBOARD = wlr_seat_get_keyboard(g_pCompositor->m_sSeat.seat);
|
||||||
|
|
||||||
|
if (!PKEYBOARD) { // ???
|
||||||
|
Debug::log(ERR, "No active keyboard in onMouseButton??");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
switch (e->state) {
|
switch (e->state) {
|
||||||
case WLR_BUTTON_PRESSED:
|
case WLR_BUTTON_PRESSED:
|
||||||
if (!g_pCompositor->m_sSeat.mouse->currentConstraint)
|
if (!g_pCompositor->m_sSeat.mouse->currentConstraint)
|
||||||
@@ -251,7 +277,7 @@ void CInputManager::newKeyboard(wlr_input_device* keyboard) {
|
|||||||
m_pActiveKeyboard->active = false;
|
m_pActiveKeyboard->active = false;
|
||||||
m_pActiveKeyboard = PNEWKEYBOARD;
|
m_pActiveKeyboard = PNEWKEYBOARD;
|
||||||
|
|
||||||
setKeyboardLayout();
|
applyConfigToKeyboard(PNEWKEYBOARD);
|
||||||
|
|
||||||
wlr_seat_set_keyboard(g_pCompositor->m_sSeat.seat, keyboard->keyboard);
|
wlr_seat_set_keyboard(g_pCompositor->m_sSeat.seat, keyboard->keyboard);
|
||||||
|
|
||||||
@@ -259,6 +285,13 @@ void CInputManager::newKeyboard(wlr_input_device* keyboard) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CInputManager::setKeyboardLayout() {
|
void CInputManager::setKeyboardLayout() {
|
||||||
|
for (auto& k : m_lKeyboards)
|
||||||
|
applyConfigToKeyboard(&k);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CInputManager::applyConfigToKeyboard(SKeyboard* pKeyboard) {
|
||||||
|
|
||||||
|
ASSERT(pKeyboard);
|
||||||
|
|
||||||
const auto RULES = g_pConfigManager->getString("input:kb_rules");
|
const auto RULES = g_pConfigManager->getString("input:kb_rules");
|
||||||
const auto MODEL = g_pConfigManager->getString("input:kb_model");
|
const auto MODEL = g_pConfigManager->getString("input:kb_model");
|
||||||
@@ -266,34 +299,41 @@ void CInputManager::setKeyboardLayout() {
|
|||||||
const auto VARIANT = g_pConfigManager->getString("input:kb_variant");
|
const auto VARIANT = g_pConfigManager->getString("input:kb_variant");
|
||||||
const auto OPTIONS = g_pConfigManager->getString("input:kb_options");
|
const auto OPTIONS = g_pConfigManager->getString("input:kb_options");
|
||||||
|
|
||||||
|
if (RULES != "" && RULES == pKeyboard->currentRules.rules && MODEL == pKeyboard->currentRules.model && LAYOUT == pKeyboard->currentRules.layout && VARIANT == pKeyboard->currentRules.variant && OPTIONS == pKeyboard->currentRules.options) {
|
||||||
|
Debug::log(LOG, "Not applying config to keyboard, it did not change.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
xkb_rule_names rules = {
|
xkb_rule_names rules = {
|
||||||
.rules = RULES.c_str(),
|
.rules = RULES.c_str(),
|
||||||
.model = MODEL.c_str(),
|
.model = MODEL.c_str(),
|
||||||
.layout = LAYOUT.c_str(),
|
.layout = LAYOUT.c_str(),
|
||||||
.variant = VARIANT.c_str(),
|
.variant = VARIANT.c_str(),
|
||||||
.options = OPTIONS.c_str()
|
.options = OPTIONS.c_str()};
|
||||||
};
|
|
||||||
|
pKeyboard->currentRules = rules;
|
||||||
|
|
||||||
const auto CONTEXT = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
|
const auto CONTEXT = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
|
||||||
const auto KEYMAP = xkb_keymap_new_from_names(CONTEXT, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS);
|
|
||||||
|
if (!CONTEXT) {
|
||||||
|
Debug::log(ERR, "applyConfigToKeyboard: CONTEXT null??");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Debug::log(LOG, "Attempting to create a keymap for layout %s with variant %s (rules: %s, model: %s, options: %s)", rules.layout, rules.variant, rules.rules, rules.model, rules.options);
|
||||||
|
|
||||||
|
auto KEYMAP = xkb_keymap_new_from_names(CONTEXT, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS);
|
||||||
|
|
||||||
if (!KEYMAP) {
|
if (!KEYMAP) {
|
||||||
Debug::log(ERR, "Keyboard layout %s with variant %s (rules: %s, model: %s, options: %s) couldn't have been loaded.", rules.layout, rules.variant, rules.rules, rules.model, rules.options);
|
Debug::log(ERR, "Keyboard layout %s with variant %s (rules: %s, model: %s, options: %s) couldn't have been loaded.", rules.layout, rules.variant, rules.rules, rules.model, rules.options);
|
||||||
xkb_context_unref(CONTEXT);
|
memset(&rules, 0, sizeof(rules));
|
||||||
return;
|
|
||||||
|
pKeyboard->currentRules = rules;
|
||||||
|
|
||||||
|
KEYMAP = xkb_keymap_new_from_names(CONTEXT, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS);
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto PLASTKEEB = m_pActiveKeyboard->keyboard->keyboard;
|
wlr_keyboard_set_keymap(pKeyboard->keyboard->keyboard, KEYMAP);
|
||||||
|
|
||||||
if (!PLASTKEEB) {
|
|
||||||
xkb_keymap_unref(KEYMAP);
|
|
||||||
xkb_context_unref(CONTEXT);
|
|
||||||
|
|
||||||
Debug::log(ERR, "No Seat Keyboard???");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
wlr_keyboard_set_keymap(PLASTKEEB, KEYMAP);
|
|
||||||
|
|
||||||
wlr_keyboard_modifiers wlrMods = {0};
|
wlr_keyboard_modifiers wlrMods = {0};
|
||||||
|
|
||||||
@@ -306,13 +346,13 @@ void CInputManager::setKeyboardLayout() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (wlrMods.locked != 0) {
|
if (wlrMods.locked != 0) {
|
||||||
wlr_seat_keyboard_notify_modifiers(g_pCompositor->m_sSeat.seat, &wlrMods);
|
wlr_keyboard_notify_modifiers(pKeyboard->keyboard->keyboard, 0, 0, wlrMods.locked, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
xkb_keymap_unref(KEYMAP);
|
xkb_keymap_unref(KEYMAP);
|
||||||
xkb_context_unref(CONTEXT);
|
xkb_context_unref(CONTEXT);
|
||||||
|
|
||||||
Debug::log(LOG, "Set the keyboard layout to %s and variant to %s", rules.layout, rules.variant);
|
Debug::log(LOG, "Set the keyboard layout to %s and variant to %s for keyboard \"%s\"", rules.layout, rules.variant, pKeyboard->keyboard->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CInputManager::newMouse(wlr_input_device* mouse) {
|
void CInputManager::newMouse(wlr_input_device* mouse) {
|
||||||
@@ -324,11 +364,30 @@ void CInputManager::newMouse(wlr_input_device* mouse) {
|
|||||||
if (wlr_input_device_is_libinput(mouse)) {
|
if (wlr_input_device_is_libinput(mouse)) {
|
||||||
const auto LIBINPUTDEV = (libinput_device*)wlr_libinput_get_device_handle(mouse);
|
const auto LIBINPUTDEV = (libinput_device*)wlr_libinput_get_device_handle(mouse);
|
||||||
|
|
||||||
|
if (g_pConfigManager->getInt("input:touchpad:clickfinger_behavior") == 0) // toggle software buttons or clickfinger
|
||||||
|
libinput_device_config_click_set_method(LIBINPUTDEV, LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS);
|
||||||
|
else
|
||||||
|
libinput_device_config_click_set_method(LIBINPUTDEV, LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER);
|
||||||
|
|
||||||
|
if (libinput_device_config_middle_emulation_is_available(LIBINPUTDEV)) { // middleclick on r+l mouse button pressed
|
||||||
|
if (g_pConfigManager->getInt("input:touchpad:middle_button_emulation") == 1)
|
||||||
|
libinput_device_config_middle_emulation_set_enabled(LIBINPUTDEV, LIBINPUT_CONFIG_MIDDLE_EMULATION_ENABLED);
|
||||||
|
else
|
||||||
|
libinput_device_config_middle_emulation_set_enabled(LIBINPUTDEV, LIBINPUT_CONFIG_MIDDLE_EMULATION_DISABLED);
|
||||||
|
}
|
||||||
|
|
||||||
if (libinput_device_config_tap_get_finger_count(LIBINPUTDEV)) // this is for tapping (like on a laptop)
|
if (libinput_device_config_tap_get_finger_count(LIBINPUTDEV)) // this is for tapping (like on a laptop)
|
||||||
|
if (g_pConfigManager->getInt("input:touchpad:tap-to-click") == 1)
|
||||||
libinput_device_config_tap_set_enabled(LIBINPUTDEV, LIBINPUT_CONFIG_TAP_ENABLED);
|
libinput_device_config_tap_set_enabled(LIBINPUTDEV, LIBINPUT_CONFIG_TAP_ENABLED);
|
||||||
|
|
||||||
if (libinput_device_config_scroll_has_natural_scroll(LIBINPUTDEV))
|
if (libinput_device_config_scroll_has_natural_scroll(LIBINPUTDEV)) {
|
||||||
|
double w = 0, h = 0;
|
||||||
|
|
||||||
|
if (libinput_device_has_capability(LIBINPUTDEV, LIBINPUT_DEVICE_CAP_POINTER) && libinput_device_get_size(LIBINPUTDEV, &w, &h) == 0) // pointer with size is a touchpad
|
||||||
|
libinput_device_config_scroll_set_natural_scroll_enabled(LIBINPUTDEV, g_pConfigManager->getInt("input:touchpad:natural_scroll"));
|
||||||
|
else
|
||||||
libinput_device_config_scroll_set_natural_scroll_enabled(LIBINPUTDEV, g_pConfigManager->getInt("input:natural_scroll"));
|
libinput_device_config_scroll_set_natural_scroll_enabled(LIBINPUTDEV, g_pConfigManager->getInt("input:natural_scroll"));
|
||||||
|
}
|
||||||
|
|
||||||
if (libinput_device_config_dwt_is_available(LIBINPUTDEV)) {
|
if (libinput_device_config_dwt_is_available(LIBINPUTDEV)) {
|
||||||
const auto DWT = static_cast<enum libinput_config_dwt_state>(g_pConfigManager->getInt("input:touchpad:disable_while_typing") != 0);
|
const auto DWT = static_cast<enum libinput_config_dwt_state>(g_pConfigManager->getInt("input:touchpad:disable_while_typing") != 0);
|
||||||
@@ -342,6 +401,8 @@ void CInputManager::newMouse(wlr_input_device* mouse) {
|
|||||||
|
|
||||||
g_pCompositor->m_sSeat.mouse = PMOUSE;
|
g_pCompositor->m_sSeat.mouse = PMOUSE;
|
||||||
|
|
||||||
|
m_tmrLastCursorMovement.reset();
|
||||||
|
|
||||||
Debug::log(LOG, "New mouse created, pointer WLR: %x", mouse);
|
Debug::log(LOG, "New mouse created, pointer WLR: %x", mouse);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -500,3 +561,23 @@ void CInputManager::constrainMouse(SMouse* pMouse, wlr_pointer_constraint_v1* co
|
|||||||
void Events::listener_commitConstraint(void* owner, void* data) {
|
void Events::listener_commitConstraint(void* owner, void* data) {
|
||||||
//g_pInputManager->recheckConstraint((SMouse*)owner);
|
//g_pInputManager->recheckConstraint((SMouse*)owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CInputManager::updateCapabilities(wlr_input_device* pDev) {
|
||||||
|
// TODO: this is dumb
|
||||||
|
|
||||||
|
switch (pDev->type) {
|
||||||
|
case WLR_INPUT_DEVICE_KEYBOARD:
|
||||||
|
m_uiCapabilities |= WL_SEAT_CAPABILITY_KEYBOARD;
|
||||||
|
break;
|
||||||
|
case WLR_INPUT_DEVICE_POINTER:
|
||||||
|
m_uiCapabilities |= WL_SEAT_CAPABILITY_POINTER;
|
||||||
|
break;
|
||||||
|
case WLR_INPUT_DEVICE_TOUCH:
|
||||||
|
m_uiCapabilities |= WL_SEAT_CAPABILITY_TOUCH;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
wlr_seat_set_capabilities(g_pCompositor->m_sSeat.seat, m_uiCapabilities);
|
||||||
|
}
|
@@ -1,9 +1,10 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "../defines.hpp"
|
#include "../../defines.hpp"
|
||||||
#include <list>
|
#include <list>
|
||||||
#include "../helpers/WLClasses.hpp"
|
#include "../../helpers/WLClasses.hpp"
|
||||||
#include "../Window.hpp"
|
#include "../../Window.hpp"
|
||||||
|
#include "../../helpers/Timer.hpp"
|
||||||
|
|
||||||
class CInputManager {
|
class CInputManager {
|
||||||
public:
|
public:
|
||||||
@@ -28,6 +29,7 @@ public:
|
|||||||
void setKeyboardLayout();
|
void setKeyboardLayout();
|
||||||
|
|
||||||
void updateDragIcon();
|
void updateDragIcon();
|
||||||
|
void updateCapabilities(wlr_input_device*);
|
||||||
|
|
||||||
|
|
||||||
// for dragging floating windows
|
// for dragging floating windows
|
||||||
@@ -40,11 +42,28 @@ public:
|
|||||||
std::list<SKeyboard> m_lKeyboards;
|
std::list<SKeyboard> m_lKeyboards;
|
||||||
std::list<SMouse> m_lMice;
|
std::list<SMouse> m_lMice;
|
||||||
|
|
||||||
|
// tablets
|
||||||
|
std::list<STablet> m_lTablets;
|
||||||
|
std::list<STabletTool> m_lTabletTools;
|
||||||
|
std::list<STabletPad> m_lTabletPads;
|
||||||
|
|
||||||
|
void newTabletTool(wlr_input_device*);
|
||||||
|
void newTabletPad(wlr_input_device*);
|
||||||
|
void focusTablet(STablet*, wlr_tablet_tool*, bool motion = false);
|
||||||
|
|
||||||
SKeyboard* m_pActiveKeyboard = nullptr;
|
SKeyboard* m_pActiveKeyboard = nullptr;
|
||||||
|
|
||||||
private:
|
CTimer m_tmrLastCursorMovement;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
uint32_t m_uiCapabilities = 0;
|
||||||
|
|
||||||
void mouseMoveUnified(uint32_t, bool refocus = false);
|
void mouseMoveUnified(uint32_t, bool refocus = false);
|
||||||
|
|
||||||
|
STabletTool* ensureTabletToolPresent(wlr_tablet_tool*);
|
||||||
|
|
||||||
|
void applyConfigToKeyboard(SKeyboard*);
|
||||||
};
|
};
|
||||||
|
|
||||||
inline std::unique_ptr<CInputManager> g_pInputManager;
|
inline std::unique_ptr<CInputManager> g_pInputManager;
|
229
src/managers/input/Tablets.cpp
Normal file
229
src/managers/input/Tablets.cpp
Normal file
@@ -0,0 +1,229 @@
|
|||||||
|
#include "InputManager.hpp"
|
||||||
|
#include "../../Compositor.hpp"
|
||||||
|
|
||||||
|
void CInputManager::newTabletTool(wlr_input_device* pDevice) {
|
||||||
|
const auto PNEWTABLET = &m_lTablets.emplace_back();
|
||||||
|
|
||||||
|
PNEWTABLET->wlrTablet = pDevice->tablet;
|
||||||
|
PNEWTABLET->wlrDevice = pDevice;
|
||||||
|
PNEWTABLET->wlrTabletV2 = wlr_tablet_create(g_pCompositor->m_sWLRTabletManager, g_pCompositor->m_sSeat.seat, pDevice);
|
||||||
|
PNEWTABLET->wlrTablet->data = PNEWTABLET;
|
||||||
|
|
||||||
|
Debug::log(LOG, "Attaching tablet to cursor!");
|
||||||
|
|
||||||
|
wlr_cursor_attach_input_device(g_pCompositor->m_sWLRCursor, pDevice);
|
||||||
|
|
||||||
|
PNEWTABLET->hyprListener_Destroy.initCallback(&pDevice->events.destroy, [](void* owner, void* data) {
|
||||||
|
const auto PTAB = (STablet*)owner;
|
||||||
|
|
||||||
|
g_pInputManager->m_lTablets.remove(*PTAB);
|
||||||
|
|
||||||
|
Debug::log(LOG, "Removed a tablet");
|
||||||
|
}, PNEWTABLET, "Tablet");
|
||||||
|
|
||||||
|
PNEWTABLET->hyprListener_Axis.initCallback(&pDevice->tablet->events.axis, [](void* owner, void* data) {
|
||||||
|
|
||||||
|
const auto EVENT = (wlr_tablet_tool_axis_event*)data;
|
||||||
|
const auto PTAB = (STablet*)owner;
|
||||||
|
|
||||||
|
switch (EVENT->tool->type) {
|
||||||
|
case WLR_TABLET_TOOL_TYPE_MOUSE:
|
||||||
|
wlr_cursor_move(g_pCompositor->m_sWLRCursor, PTAB->wlrDevice, EVENT->dx, EVENT->dy);
|
||||||
|
g_pInputManager->refocus();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
double x = (EVENT->updated_axes & WLR_TABLET_TOOL_AXIS_X) ? EVENT->x : NAN;
|
||||||
|
double y = (EVENT->updated_axes & WLR_TABLET_TOOL_AXIS_Y) ? EVENT->y : NAN;
|
||||||
|
wlr_cursor_warp_absolute(g_pCompositor->m_sWLRCursor, PTAB->wlrDevice, x, y);
|
||||||
|
g_pInputManager->refocus();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto PTOOL = g_pInputManager->ensureTabletToolPresent(EVENT->tool);
|
||||||
|
|
||||||
|
// TODO: this might be wrong
|
||||||
|
if (PTOOL->active) {
|
||||||
|
g_pInputManager->refocus();
|
||||||
|
|
||||||
|
g_pInputManager->focusTablet(PTAB, EVENT->tool, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (EVENT->updated_axes & WLR_TABLET_TOOL_AXIS_PRESSURE)
|
||||||
|
wlr_tablet_v2_tablet_tool_notify_pressure(PTOOL->wlrTabletToolV2, EVENT->pressure);
|
||||||
|
|
||||||
|
if (EVENT->updated_axes & WLR_TABLET_TOOL_AXIS_DISTANCE)
|
||||||
|
wlr_tablet_v2_tablet_tool_notify_distance(PTOOL->wlrTabletToolV2, EVENT->distance);
|
||||||
|
|
||||||
|
if (EVENT->updated_axes & WLR_TABLET_TOOL_AXIS_ROTATION)
|
||||||
|
wlr_tablet_v2_tablet_tool_notify_rotation(PTOOL->wlrTabletToolV2, EVENT->rotation);
|
||||||
|
|
||||||
|
if (EVENT->updated_axes & WLR_TABLET_TOOL_AXIS_SLIDER)
|
||||||
|
wlr_tablet_v2_tablet_tool_notify_slider(PTOOL->wlrTabletToolV2, EVENT->slider);
|
||||||
|
|
||||||
|
if (EVENT->updated_axes & WLR_TABLET_TOOL_AXIS_WHEEL)
|
||||||
|
wlr_tablet_v2_tablet_tool_notify_wheel(PTOOL->wlrTabletToolV2, EVENT->wheel_delta, 0);
|
||||||
|
|
||||||
|
if (EVENT->updated_axes & WLR_TABLET_TOOL_AXIS_TILT_X)
|
||||||
|
PTOOL->tiltX = EVENT->tilt_x;
|
||||||
|
|
||||||
|
if (EVENT->updated_axes & WLR_TABLET_TOOL_AXIS_TILT_Y)
|
||||||
|
PTOOL->tiltY = EVENT->tilt_y;
|
||||||
|
|
||||||
|
if (EVENT->updated_axes & (WLR_TABLET_TOOL_AXIS_TILT_X | WLR_TABLET_TOOL_AXIS_TILT_Y))
|
||||||
|
wlr_tablet_v2_tablet_tool_notify_tilt(PTOOL->wlrTabletToolV2, PTOOL->tiltX, PTOOL->tiltY);
|
||||||
|
|
||||||
|
}, PNEWTABLET, "Tablet");
|
||||||
|
|
||||||
|
PNEWTABLET->hyprListener_Tip.initCallback(&pDevice->tablet->events.tip, [](void* owner, void* data) {
|
||||||
|
const auto EVENT = (wlr_tablet_tool_tip_event*)data;
|
||||||
|
const auto PTAB = (STablet*)owner;
|
||||||
|
|
||||||
|
const auto PTOOL = g_pInputManager->ensureTabletToolPresent(EVENT->tool);
|
||||||
|
|
||||||
|
// TODO: this might be wrong
|
||||||
|
if (EVENT->state == WLR_TABLET_TOOL_TIP_DOWN) {
|
||||||
|
g_pInputManager->refocus();
|
||||||
|
g_pInputManager->focusTablet(PTAB, EVENT->tool);
|
||||||
|
wlr_send_tablet_v2_tablet_tool_down(PTOOL->wlrTabletToolV2);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
wlr_send_tablet_v2_tablet_tool_up(PTOOL->wlrTabletToolV2);
|
||||||
|
}
|
||||||
|
|
||||||
|
}, PNEWTABLET, "Tablet");
|
||||||
|
|
||||||
|
PNEWTABLET->hyprListener_Button.initCallback(&pDevice->tablet->events.button, [](void* owner, void* data) {
|
||||||
|
const auto EVENT = (wlr_tablet_tool_button_event*)data;
|
||||||
|
|
||||||
|
const auto PTOOL = g_pInputManager->ensureTabletToolPresent(EVENT->tool);
|
||||||
|
|
||||||
|
wlr_tablet_v2_tablet_tool_notify_button(PTOOL->wlrTabletToolV2, (zwp_tablet_pad_v2_button_state)EVENT->button, (zwp_tablet_pad_v2_button_state)EVENT->state);
|
||||||
|
|
||||||
|
}, PNEWTABLET, "Tablet");
|
||||||
|
|
||||||
|
PNEWTABLET->hyprListener_Proximity.initCallback(&pDevice->tablet->events.proximity, [](void* owner, void* data) {
|
||||||
|
const auto EVENT = (wlr_tablet_tool_proximity_event*)data;
|
||||||
|
const auto PTAB = (STablet*)owner;
|
||||||
|
|
||||||
|
const auto PTOOL = g_pInputManager->ensureTabletToolPresent(EVENT->tool);
|
||||||
|
|
||||||
|
if (EVENT->state == WLR_TABLET_TOOL_PROXIMITY_OUT) {
|
||||||
|
PTOOL->active = false;
|
||||||
|
|
||||||
|
if (PTOOL->pSurface) {
|
||||||
|
wlr_tablet_v2_tablet_tool_notify_proximity_out(PTOOL->wlrTabletToolV2);
|
||||||
|
PTOOL->pSurface = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
PTOOL->active = true;
|
||||||
|
g_pInputManager->refocus();
|
||||||
|
g_pInputManager->focusTablet(PTAB, EVENT->tool);
|
||||||
|
}
|
||||||
|
|
||||||
|
}, PNEWTABLET, "Tablet");
|
||||||
|
}
|
||||||
|
|
||||||
|
STabletTool* CInputManager::ensureTabletToolPresent(wlr_tablet_tool* pTool) {
|
||||||
|
if (pTool->data == nullptr) {
|
||||||
|
const auto PTOOL = &m_lTabletTools.emplace_back();
|
||||||
|
|
||||||
|
Debug::log(LOG, "Creating tablet tool v2 for %x", pTool);
|
||||||
|
|
||||||
|
PTOOL->wlrTabletTool = pTool;
|
||||||
|
pTool->data = PTOOL;
|
||||||
|
|
||||||
|
PTOOL->wlrTabletToolV2 = wlr_tablet_tool_create(g_pCompositor->m_sWLRTabletManager, g_pCompositor->m_sSeat.seat, pTool);
|
||||||
|
|
||||||
|
PTOOL->hyprListener_TabletToolDestroy.initCallback(&pTool->events.destroy, [](void* owner, void* data) {
|
||||||
|
const auto PTOOL = (STabletTool*)owner;
|
||||||
|
|
||||||
|
PTOOL->wlrTabletTool->data = nullptr;
|
||||||
|
g_pInputManager->m_lTabletTools.remove(*PTOOL);
|
||||||
|
}, PTOOL, "Tablet Tool V1");
|
||||||
|
|
||||||
|
//TODO: set cursor request
|
||||||
|
}
|
||||||
|
|
||||||
|
return (STabletTool*)pTool->data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CInputManager::newTabletPad(wlr_input_device* pDevice) {
|
||||||
|
const auto PNEWPAD = &m_lTabletPads.emplace_back();
|
||||||
|
|
||||||
|
PNEWPAD->wlrTabletPadV2 = wlr_tablet_pad_create(g_pCompositor->m_sWLRTabletManager, g_pCompositor->m_sSeat.seat, pDevice);
|
||||||
|
|
||||||
|
PNEWPAD->hyprListener_Button.initCallback(&pDevice->tablet_pad->events.button, [](void* owner, void* data) {
|
||||||
|
|
||||||
|
const auto EVENT = (wlr_tablet_pad_button_event*)data;
|
||||||
|
const auto PPAD = (STabletPad*)owner;
|
||||||
|
|
||||||
|
wlr_tablet_v2_tablet_pad_notify_mode(PPAD->wlrTabletPadV2, EVENT->group, EVENT->mode, EVENT->time_msec);
|
||||||
|
wlr_tablet_v2_tablet_pad_notify_button(PPAD->wlrTabletPadV2, EVENT->button, EVENT->time_msec, (zwp_tablet_pad_v2_button_state)EVENT->state);
|
||||||
|
|
||||||
|
}, PNEWPAD, "Tablet Pad");
|
||||||
|
|
||||||
|
PNEWPAD->hyprListener_Strip.initCallback(&pDevice->tablet_pad->events.strip, [](void* owner, void* data) {
|
||||||
|
|
||||||
|
const auto EVENT = (wlr_tablet_pad_strip_event*)data;
|
||||||
|
const auto PPAD = (STabletPad*)owner;
|
||||||
|
|
||||||
|
wlr_tablet_v2_tablet_pad_notify_strip(PPAD->wlrTabletPadV2, EVENT->strip, EVENT->position, EVENT->source == WLR_TABLET_PAD_STRIP_SOURCE_FINGER, EVENT->time_msec);
|
||||||
|
|
||||||
|
}, PNEWPAD, "Tablet Pad");
|
||||||
|
|
||||||
|
PNEWPAD->hyprListener_Ring.initCallback(&pDevice->tablet_pad->events.strip, [](void* owner, void* data) {
|
||||||
|
|
||||||
|
const auto EVENT = (wlr_tablet_pad_ring_event*)data;
|
||||||
|
const auto PPAD = (STabletPad*)owner;
|
||||||
|
|
||||||
|
wlr_tablet_v2_tablet_pad_notify_ring(PPAD->wlrTabletPadV2, EVENT->ring, EVENT->position, EVENT->source == WLR_TABLET_PAD_RING_SOURCE_FINGER, EVENT->time_msec);
|
||||||
|
|
||||||
|
}, PNEWPAD, "Tablet Pad");
|
||||||
|
|
||||||
|
PNEWPAD->hyprListener_Attach.initCallback(&pDevice->tablet_pad->events.strip, [](void* owner, void* data) {
|
||||||
|
|
||||||
|
const auto TABLET = (wlr_tablet_tool*)data;
|
||||||
|
const auto PPAD = (STabletPad*)owner;
|
||||||
|
|
||||||
|
PPAD->pTabletParent = (STablet*)TABLET->data;
|
||||||
|
|
||||||
|
if (!PPAD->pTabletParent)
|
||||||
|
Debug::log(ERR, "tabletpad got attached to a nullptr tablet!! this might be bad.");
|
||||||
|
|
||||||
|
}, PNEWPAD, "Tablet Pad");
|
||||||
|
|
||||||
|
PNEWPAD->hyprListener_Destroy.initCallback(&pDevice->events.destroy, [](void* owner, void* data) {
|
||||||
|
|
||||||
|
const auto PPAD = (STabletPad*)owner;
|
||||||
|
|
||||||
|
g_pInputManager->m_lTabletPads.remove(*PPAD);
|
||||||
|
|
||||||
|
Debug::log(LOG, "Removed a tablet pad");
|
||||||
|
|
||||||
|
}, PNEWPAD, "Tablet Pad");
|
||||||
|
}
|
||||||
|
|
||||||
|
void CInputManager::focusTablet(STablet* pTab, wlr_tablet_tool* pTool, bool motion) {
|
||||||
|
const auto PTOOL = g_pInputManager->ensureTabletToolPresent(pTool);
|
||||||
|
|
||||||
|
if (const auto PWINDOW = g_pCompositor->m_pLastWindow; g_pCompositor->windowValidMapped(PWINDOW)) {
|
||||||
|
const auto CURSORPOS = g_pInputManager->getMouseCoordsInternal();
|
||||||
|
|
||||||
|
const auto LOCAL = CURSORPOS - PWINDOW->m_vRealPosition.goalv();
|
||||||
|
|
||||||
|
if (PTOOL->pSurface != g_pCompositor->m_pLastFocus)
|
||||||
|
wlr_tablet_v2_tablet_tool_notify_proximity_out(PTOOL->wlrTabletToolV2);
|
||||||
|
|
||||||
|
if (g_pCompositor->m_pLastFocus) {
|
||||||
|
PTOOL->pSurface = g_pCompositor->m_pLastFocus;
|
||||||
|
wlr_tablet_v2_tablet_tool_notify_proximity_in(PTOOL->wlrTabletToolV2, pTab->wlrTabletV2, g_pCompositor->m_pLastFocus);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (motion)
|
||||||
|
wlr_tablet_v2_tablet_tool_notify_motion(PTOOL->wlrTabletToolV2, LOCAL.x, LOCAL.y);
|
||||||
|
} else {
|
||||||
|
if (PTOOL->pSurface)
|
||||||
|
wlr_tablet_v2_tablet_tool_notify_proximity_out(PTOOL->wlrTabletToolV2);
|
||||||
|
}
|
||||||
|
}
|
25
src/meson.build
Normal file
25
src/meson.build
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
globber = run_command('find', '-name', '*.cpp', check: true)
|
||||||
|
src = globber.stdout().strip().split('\n')
|
||||||
|
|
||||||
|
executable('Hyprland', src,
|
||||||
|
cpp_args: ['-DWLR_USE_UNSTABLE'],
|
||||||
|
dependencies: [
|
||||||
|
server_protos,
|
||||||
|
dependency('wayland-server'),
|
||||||
|
dependency('wayland-client'),
|
||||||
|
wlroots.get_variable('wlroots'),
|
||||||
|
dependency('cairo'),
|
||||||
|
dependency('pango'),
|
||||||
|
dependency('pangocairo'),
|
||||||
|
dependency('libdrm'),
|
||||||
|
dependency('egl'),
|
||||||
|
dependency('xkbcommon'),
|
||||||
|
dependency('libinput'),
|
||||||
|
xcb_dep,
|
||||||
|
|
||||||
|
dependency('pixman-1'),
|
||||||
|
dependency('GL'),
|
||||||
|
dependency('threads')
|
||||||
|
],
|
||||||
|
install : true
|
||||||
|
)
|
@@ -75,6 +75,18 @@ CHyprOpenGLImpl::CHyprOpenGLImpl() {
|
|||||||
m_shBLUR2.posAttrib = glGetAttribLocation(prog, "pos");
|
m_shBLUR2.posAttrib = glGetAttribLocation(prog, "pos");
|
||||||
m_shBLUR2.texAttrib = glGetAttribLocation(prog, "texcoord");
|
m_shBLUR2.texAttrib = glGetAttribLocation(prog, "texcoord");
|
||||||
|
|
||||||
|
prog = createProgram(QUADVERTSRC, FRAGSHADOW);
|
||||||
|
m_shSHADOW.program = prog;
|
||||||
|
m_shSHADOW.proj = glGetUniformLocation(prog, "proj");
|
||||||
|
m_shSHADOW.posAttrib = glGetAttribLocation(prog, "pos");
|
||||||
|
m_shSHADOW.texAttrib = glGetAttribLocation(prog, "texcoord");
|
||||||
|
|
||||||
|
prog = createProgram(QUADVERTSRC, FRAGBORDER1);
|
||||||
|
m_shBORDER1.program = prog;
|
||||||
|
m_shBORDER1.proj = glGetUniformLocation(prog, "proj");
|
||||||
|
m_shBORDER1.posAttrib = glGetAttribLocation(prog, "pos");
|
||||||
|
m_shBORDER1.texAttrib = glGetAttribLocation(prog, "texcoord");
|
||||||
|
|
||||||
Debug::log(LOG, "Shaders initialized successfully.");
|
Debug::log(LOG, "Shaders initialized successfully.");
|
||||||
|
|
||||||
// End shaders
|
// End shaders
|
||||||
@@ -240,6 +252,10 @@ void CHyprOpenGLImpl::scissor(const int x, const int y, const int w, const int h
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CHyprOpenGLImpl::renderRect(wlr_box* box, const CColor& col, int round) {
|
void CHyprOpenGLImpl::renderRect(wlr_box* box, const CColor& col, int round) {
|
||||||
|
renderRectWithDamage(box, col, m_RenderData.pDamage, round);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CHyprOpenGLImpl::renderRectWithDamage(wlr_box* box, const CColor& col, pixman_region32_t* damage, int round) {
|
||||||
RASSERT((box->width > 0 && box->height > 0), "Tried to render rect with width/height < 0!");
|
RASSERT((box->width > 0 && box->height > 0), "Tried to render rect with width/height < 0!");
|
||||||
RASSERT(m_RenderData.pMonitor, "Tried to render rect without begin()!");
|
RASSERT(m_RenderData.pMonitor, "Tried to render rect without begin()!");
|
||||||
|
|
||||||
@@ -264,12 +280,14 @@ void CHyprOpenGLImpl::renderRect(wlr_box* box, const CColor& col, int round) {
|
|||||||
const auto BOTTOMRIGHT = Vector2D(box->width - round, box->height - round);
|
const auto BOTTOMRIGHT = Vector2D(box->width - round, box->height - round);
|
||||||
const auto FULLSIZE = Vector2D(box->width, box->height);
|
const auto FULLSIZE = Vector2D(box->width, box->height);
|
||||||
|
|
||||||
|
static auto *const PMULTISAMPLEEDGES = &g_pConfigManager->getConfigValuePtr("decoration:multisample_edges")->intValue;
|
||||||
|
|
||||||
// Rounded corners
|
// Rounded corners
|
||||||
glUniform2f(glGetUniformLocation(m_shQUAD.program, "topLeft"), (float)TOPLEFT.x, (float)TOPLEFT.y);
|
glUniform2f(glGetUniformLocation(m_shQUAD.program, "topLeft"), (float)TOPLEFT.x, (float)TOPLEFT.y);
|
||||||
glUniform2f(glGetUniformLocation(m_shQUAD.program, "bottomRight"), (float)BOTTOMRIGHT.x, (float)BOTTOMRIGHT.y);
|
glUniform2f(glGetUniformLocation(m_shQUAD.program, "bottomRight"), (float)BOTTOMRIGHT.x, (float)BOTTOMRIGHT.y);
|
||||||
glUniform2f(glGetUniformLocation(m_shQUAD.program, "fullSize"), (float)FULLSIZE.x, (float)FULLSIZE.y);
|
glUniform2f(glGetUniformLocation(m_shQUAD.program, "fullSize"), (float)FULLSIZE.x, (float)FULLSIZE.y);
|
||||||
glUniform1f(glGetUniformLocation(m_shQUAD.program, "radius"), round);
|
glUniform1f(glGetUniformLocation(m_shQUAD.program, "radius"), round);
|
||||||
glUniform1i(glGetUniformLocation(m_shQUAD.program, "primitiveMultisample"), (int)(g_pConfigManager->getInt("decoration:multisample_edges") == 1 && round != 0));
|
glUniform1i(glGetUniformLocation(m_shQUAD.program, "primitiveMultisample"), (int)(*PMULTISAMPLEEDGES == 1 && round != 0));
|
||||||
|
|
||||||
glVertexAttribPointer(m_shQUAD.posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
|
glVertexAttribPointer(m_shQUAD.posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
|
||||||
glVertexAttribPointer(m_shQUAD.texAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
|
glVertexAttribPointer(m_shQUAD.texAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
|
||||||
@@ -277,8 +295,8 @@ void CHyprOpenGLImpl::renderRect(wlr_box* box, const CColor& col, int round) {
|
|||||||
glEnableVertexAttribArray(m_shQUAD.posAttrib);
|
glEnableVertexAttribArray(m_shQUAD.posAttrib);
|
||||||
glEnableVertexAttribArray(m_shQUAD.texAttrib);
|
glEnableVertexAttribArray(m_shQUAD.texAttrib);
|
||||||
|
|
||||||
if (pixman_region32_not_empty(m_RenderData.pDamage)) {
|
if (pixman_region32_not_empty(damage)) {
|
||||||
PIXMAN_DAMAGE_FOREACH(m_RenderData.pDamage) {
|
PIXMAN_DAMAGE_FOREACH(damage) {
|
||||||
const auto RECT = RECTSARR[i];
|
const auto RECT = RECTSARR[i];
|
||||||
scissor(&RECT);
|
scissor(&RECT);
|
||||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||||
@@ -297,15 +315,15 @@ void CHyprOpenGLImpl::renderTexture(wlr_texture* tex, wlr_box* pBox, float alpha
|
|||||||
renderTexture(CTexture(tex), pBox, alpha, round);
|
renderTexture(CTexture(tex), pBox, alpha, round);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CHyprOpenGLImpl::renderTexture(const CTexture& tex, wlr_box* pBox, float alpha, int round, bool discardopaque, bool border) {
|
void CHyprOpenGLImpl::renderTexture(const CTexture& tex, wlr_box* pBox, float alpha, int round, bool discardopaque, bool allowPrimary) {
|
||||||
RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!");
|
RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!");
|
||||||
|
|
||||||
renderTextureInternalWithDamage(tex, pBox, alpha, m_RenderData.pDamage, round, discardopaque, border);
|
renderTextureInternalWithDamage(tex, pBox, alpha, m_RenderData.pDamage, round, discardopaque, false, allowPrimary);
|
||||||
|
|
||||||
scissor((wlr_box*)nullptr);
|
scissor((wlr_box*)nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_box* pBox, float alpha, pixman_region32_t* damage, int round, bool discardOpaque, bool border, bool noAA) {
|
void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_box* pBox, float alpha, pixman_region32_t* damage, int round, bool discardOpaque, bool noAA, bool allowPrimary) {
|
||||||
RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!");
|
RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!");
|
||||||
RASSERT((tex.m_iTexID > 0), "Attempted to draw NULL texture!");
|
RASSERT((tex.m_iTexID > 0), "Attempted to draw NULL texture!");
|
||||||
|
|
||||||
@@ -355,33 +373,35 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_b
|
|||||||
// so we need to do some maf
|
// so we need to do some maf
|
||||||
|
|
||||||
const auto TOPLEFT = Vector2D(round, round);
|
const auto TOPLEFT = Vector2D(round, round);
|
||||||
const auto BOTTOMRIGHT = Vector2D(tex.m_vSize.x - round, tex.m_vSize.y - round);
|
const auto BOTTOMRIGHT = Vector2D(pBox->width - round, pBox->height - round);
|
||||||
const auto FULLSIZE = tex.m_vSize;
|
const auto FULLSIZE = Vector2D(pBox->width, pBox->height);
|
||||||
|
static auto *const PMULTISAMPLEEDGES = &g_pConfigManager->getConfigValuePtr("decoration:multisample_edges")->intValue;
|
||||||
|
|
||||||
// Rounded corners
|
// Rounded corners
|
||||||
glUniform2f(glGetUniformLocation(shader->program, "topLeft"), (float)TOPLEFT.x, (float)TOPLEFT.y);
|
glUniform2f(glGetUniformLocation(shader->program, "topLeft"), (float)TOPLEFT.x, (float)TOPLEFT.y);
|
||||||
glUniform2f(glGetUniformLocation(shader->program, "bottomRight"), (float)BOTTOMRIGHT.x, (float)BOTTOMRIGHT.y);
|
glUniform2f(glGetUniformLocation(shader->program, "bottomRight"), (float)BOTTOMRIGHT.x, (float)BOTTOMRIGHT.y);
|
||||||
glUniform2f(glGetUniformLocation(shader->program, "fullSize"), (float)FULLSIZE.x, (float)FULLSIZE.y);
|
glUniform2f(glGetUniformLocation(shader->program, "fullSize"), (float)FULLSIZE.x, (float)FULLSIZE.y);
|
||||||
glUniform1f(glGetUniformLocation(shader->program, "radius"), round);
|
glUniform1f(glGetUniformLocation(shader->program, "radius"), round);
|
||||||
glUniform1i(glGetUniformLocation(shader->program, "primitiveMultisample"), (int)(g_pConfigManager->getInt("decoration:multisample_edges") == 1 && round != 0 && !border && !noAA));
|
glUniform1i(glGetUniformLocation(shader->program, "primitiveMultisample"), (int)(*PMULTISAMPLEEDGES == 1 && round != 0 && !noAA));
|
||||||
|
|
||||||
glVertexAttribPointer(shader->posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
|
glVertexAttribPointer(shader->posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
|
||||||
|
|
||||||
|
if (allowPrimary && m_RenderData.renderingPrimarySurface && m_RenderData.primarySurfaceUVTopLeft != Vector2D(-1, -1)) {
|
||||||
|
const float verts[] = {
|
||||||
|
m_RenderData.primarySurfaceUVBottomRight.x, m_RenderData.primarySurfaceUVTopLeft.y, // top right
|
||||||
|
m_RenderData.primarySurfaceUVTopLeft.x, m_RenderData.primarySurfaceUVTopLeft.y, // top left
|
||||||
|
m_RenderData.primarySurfaceUVBottomRight.x, m_RenderData.primarySurfaceUVBottomRight.y, // bottom right
|
||||||
|
m_RenderData.primarySurfaceUVTopLeft.x, m_RenderData.primarySurfaceUVBottomRight.y, // bottom left
|
||||||
|
};
|
||||||
|
|
||||||
|
glVertexAttribPointer(shader->texAttrib, 2, GL_FLOAT, GL_FALSE, 0, verts);
|
||||||
|
} else {
|
||||||
glVertexAttribPointer(shader->texAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
|
glVertexAttribPointer(shader->texAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
|
||||||
|
}
|
||||||
|
|
||||||
glEnableVertexAttribArray(shader->posAttrib);
|
glEnableVertexAttribArray(shader->posAttrib);
|
||||||
glEnableVertexAttribArray(shader->texAttrib);
|
glEnableVertexAttribArray(shader->texAttrib);
|
||||||
|
|
||||||
// stencil for when we want a border
|
|
||||||
if (border) {
|
|
||||||
glClearStencil(0);
|
|
||||||
glClear(GL_STENCIL_BUFFER_BIT);
|
|
||||||
|
|
||||||
glEnable(GL_STENCIL_TEST);
|
|
||||||
|
|
||||||
glStencilFunc(GL_ALWAYS, 1, -1);
|
|
||||||
glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pixman_region32_not_empty(m_RenderData.pDamage)) {
|
if (pixman_region32_not_empty(m_RenderData.pDamage)) {
|
||||||
PIXMAN_DAMAGE_FOREACH(m_RenderData.pDamage) {
|
PIXMAN_DAMAGE_FOREACH(m_RenderData.pDamage) {
|
||||||
const auto RECT = RECTSARR[i];
|
const auto RECT = RECTSARR[i];
|
||||||
@@ -390,27 +410,10 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_b
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (border) {
|
|
||||||
glStencilFunc(GL_EQUAL, 1, -1);
|
|
||||||
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
|
|
||||||
}
|
|
||||||
|
|
||||||
glDisableVertexAttribArray(shader->posAttrib);
|
glDisableVertexAttribArray(shader->posAttrib);
|
||||||
glDisableVertexAttribArray(shader->texAttrib);
|
glDisableVertexAttribArray(shader->texAttrib);
|
||||||
|
|
||||||
glBindTexture(tex.m_iTarget, 0);
|
glBindTexture(tex.m_iTarget, 0);
|
||||||
|
|
||||||
// if border draw
|
|
||||||
// we dont disable stencil here if we havent touched it.
|
|
||||||
// some other func might be using it.
|
|
||||||
if (border) {
|
|
||||||
auto BORDERCOL = m_pCurrentWindow->m_cRealBorderColor.col();
|
|
||||||
BORDERCOL.a *= alpha / 255.f;
|
|
||||||
renderBorder(pBox, BORDERCOL, g_pConfigManager->getInt("general:border_size"), round);
|
|
||||||
glStencilMask(-1);
|
|
||||||
glStencilFunc(GL_ALWAYS, 1, 0xFF);
|
|
||||||
glDisable(GL_STENCIL_TEST);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// This probably isn't the fastest
|
// This probably isn't the fastest
|
||||||
@@ -434,14 +437,14 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, wlr_box* p
|
|||||||
wlr_matrix_transpose(glMatrix, glMatrix);
|
wlr_matrix_transpose(glMatrix, glMatrix);
|
||||||
|
|
||||||
// get the config settings
|
// get the config settings
|
||||||
const auto BLURSIZE = g_pConfigManager->getInt("decoration:blur_size");
|
static auto *const PBLURSIZE = &g_pConfigManager->getConfigValuePtr("decoration:blur_size")->intValue;
|
||||||
const auto BLURPASSES = g_pConfigManager->getInt("decoration:blur_passes");
|
static auto *const PBLURPASSES = &g_pConfigManager->getConfigValuePtr("decoration:blur_passes")->intValue;
|
||||||
|
|
||||||
// prep damage
|
// prep damage
|
||||||
pixman_region32_t damage;
|
pixman_region32_t damage;
|
||||||
pixman_region32_init(&damage);
|
pixman_region32_init(&damage);
|
||||||
pixman_region32_copy(&damage, originalDamage);
|
pixman_region32_copy(&damage, originalDamage);
|
||||||
wlr_region_expand(&damage, &damage, pow(2, BLURPASSES) * BLURSIZE);
|
wlr_region_expand(&damage, &damage, pow(2, *PBLURPASSES) * *PBLURSIZE);
|
||||||
|
|
||||||
// helper
|
// helper
|
||||||
const auto PMIRRORFB = &m_mMonitorRenderResources[m_RenderData.pMonitor].mirrorFB;
|
const auto PMIRRORFB = &m_mMonitorRenderResources[m_RenderData.pMonitor].mirrorFB;
|
||||||
@@ -466,7 +469,7 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, wlr_box* p
|
|||||||
|
|
||||||
// prep two shaders
|
// prep two shaders
|
||||||
glUniformMatrix3fv(pShader->proj, 1, GL_FALSE, glMatrix);
|
glUniformMatrix3fv(pShader->proj, 1, GL_FALSE, glMatrix);
|
||||||
glUniform1f(glGetUniformLocation(pShader->program, "radius"), BLURSIZE * (a / 255.f)); // this makes the blursize change with a
|
glUniform1f(glGetUniformLocation(pShader->program, "radius"), *PBLURSIZE * (a / 255.f)); // this makes the blursize change with a
|
||||||
if (pShader == &m_shBLUR1)
|
if (pShader == &m_shBLUR1)
|
||||||
glUniform2f(glGetUniformLocation(m_shBLUR1.program, "halfpixel"), 0.5f / (m_RenderData.pMonitor->vecPixelSize.x / 2.f), 0.5f / (m_RenderData.pMonitor->vecPixelSize.y / 2.f));
|
glUniform2f(glGetUniformLocation(m_shBLUR1.program, "halfpixel"), 0.5f / (m_RenderData.pMonitor->vecPixelSize.x / 2.f), 0.5f / (m_RenderData.pMonitor->vecPixelSize.y / 2.f));
|
||||||
else
|
else
|
||||||
@@ -510,12 +513,12 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, wlr_box* p
|
|||||||
drawPass(&m_shBLUR1, &tempDamage);
|
drawPass(&m_shBLUR1, &tempDamage);
|
||||||
|
|
||||||
// and draw
|
// and draw
|
||||||
for (int i = 1; i < BLURPASSES; ++i) {
|
for (int i = 1; i < *PBLURPASSES; ++i) {
|
||||||
wlr_region_scale(&tempDamage, &damage, 1.f / (1 << (i + 1)));
|
wlr_region_scale(&tempDamage, &damage, 1.f / (1 << (i + 1)));
|
||||||
drawPass(&m_shBLUR1, &tempDamage); // down
|
drawPass(&m_shBLUR1, &tempDamage); // down
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = BLURPASSES - 1; i >= 0; --i) {
|
for (int i = *PBLURPASSES - 1; i >= 0; --i) {
|
||||||
wlr_region_scale(&tempDamage, &damage, 1.f / (1 << i)); // when upsampling we make the region twice as big
|
wlr_region_scale(&tempDamage, &damage, 1.f / (1 << i)); // when upsampling we make the region twice as big
|
||||||
drawPass(&m_shBLUR2, &tempDamage); // up
|
drawPass(&m_shBLUR2, &tempDamage); // up
|
||||||
}
|
}
|
||||||
@@ -532,11 +535,14 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, wlr_box* p
|
|||||||
return currentRenderToFB;
|
return currentRenderToFB;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, wlr_box* pBox, float a, wlr_surface* pSurface, int round, bool border) {
|
void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, wlr_box* pBox, float a, wlr_surface* pSurface, int round) {
|
||||||
RASSERT(m_RenderData.pMonitor, "Tried to render texture with blur without begin()!");
|
RASSERT(m_RenderData.pMonitor, "Tried to render texture with blur without begin()!");
|
||||||
|
|
||||||
if (g_pConfigManager->getInt("decoration:blur") == 0) {
|
static auto *const PBLURENABLED = &g_pConfigManager->getConfigValuePtr("decoration:blur")->intValue;
|
||||||
renderTexture(tex, pBox, a, round, false, border);
|
static auto* const PNOBLUROVERSIZED = &g_pConfigManager->getConfigValuePtr("decoration:no_blur_on_oversized")->intValue;
|
||||||
|
|
||||||
|
if (*PBLURENABLED == 0 || (*PNOBLUROVERSIZED && m_RenderData.primarySurfaceUVTopLeft != Vector2D(-1, -1)) || (m_pCurrentWindow && m_pCurrentWindow->m_sAdditionalConfigData.forceNoBlur)) {
|
||||||
|
renderTexture(tex, pBox, a, round, false, true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -558,8 +564,10 @@ void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, wlr_box* pBox,
|
|||||||
pixman_region32_copy(&inverseOpaque, &damage);
|
pixman_region32_copy(&inverseOpaque, &damage);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!pixman_region32_not_empty(&damage))
|
if (!pixman_region32_not_empty(&inverseOpaque)) {
|
||||||
return; // if its empty, reject.
|
renderTexture(tex, pBox, a, round, false); // reject blurring a fully opaque window
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// blur the main FB, it will be rendered onto the mirror
|
// blur the main FB, it will be rendered onto the mirror
|
||||||
const auto POUTFB = blurMainFramebufferWithDamage(a, pBox, &inverseOpaque);
|
const auto POUTFB = blurMainFramebufferWithDamage(a, pBox, &inverseOpaque);
|
||||||
@@ -590,34 +598,20 @@ void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, wlr_box* pBox,
|
|||||||
wlr_box MONITORBOX = {0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y};
|
wlr_box MONITORBOX = {0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y};
|
||||||
if (pixman_region32_not_empty(&damage)) {
|
if (pixman_region32_not_empty(&damage)) {
|
||||||
// render our great blurred FB
|
// render our great blurred FB
|
||||||
renderTextureInternalWithDamage(POUTFB->m_cTex, &MONITORBOX, g_pConfigManager->getInt("decoration:blur_ignore_opacity") ? 255.f : a, &damage);
|
static auto *const PBLURIGNOREOPACITY = &g_pConfigManager->getConfigValuePtr("decoration:blur_ignore_opacity")->intValue;
|
||||||
|
renderTextureInternalWithDamage(POUTFB->m_cTex, &MONITORBOX, *PBLURIGNOREOPACITY ? 255.f : a, &damage, 0, false, false, true);
|
||||||
|
|
||||||
// render the window, but clear stencil
|
// render the window, but clear stencil
|
||||||
glClearStencil(0);
|
glClearStencil(0);
|
||||||
glClear(GL_STENCIL_BUFFER_BIT);
|
glClear(GL_STENCIL_BUFFER_BIT);
|
||||||
|
|
||||||
// and write to it
|
// draw window
|
||||||
glStencilFunc(GL_ALWAYS, 1, -1);
|
glDisable(GL_STENCIL_TEST);
|
||||||
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
|
|
||||||
|
|
||||||
renderTextureInternalWithDamage(tex, pBox, a, &damage, round, false, false, true);
|
renderTextureInternalWithDamage(tex, pBox, a, &damage, round, false, false, true);
|
||||||
|
|
||||||
// then stop
|
|
||||||
glStencilFunc(GL_EQUAL, 1, -1);
|
|
||||||
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// disable the stencil (if no border), finalize everything
|
|
||||||
if (!border) {
|
|
||||||
glStencilMask(-1);
|
glStencilMask(-1);
|
||||||
glStencilFunc(GL_ALWAYS, 1, 0xFF);
|
glStencilFunc(GL_ALWAYS, 1, 0xFF);
|
||||||
} else {
|
|
||||||
auto BORDERCOL = m_pCurrentWindow->m_cRealBorderColor.col();
|
|
||||||
BORDERCOL.a *= a / 255.f;
|
|
||||||
renderBorder(pBox, BORDERCOL, g_pConfigManager->getInt("general:border_size"), round);
|
|
||||||
}
|
|
||||||
|
|
||||||
glDisable(GL_STENCIL_TEST);
|
|
||||||
pixman_region32_fini(&damage);
|
pixman_region32_fini(&damage);
|
||||||
scissor((wlr_box*)nullptr);
|
scissor((wlr_box*)nullptr);
|
||||||
}
|
}
|
||||||
@@ -629,23 +623,67 @@ void pushVert2D(float x, float y, float* arr, int& counter, wlr_box* box) {
|
|||||||
counter++;
|
counter++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CHyprOpenGLImpl::renderBorder(wlr_box* box, const CColor& col, int thick, int round) {
|
void CHyprOpenGLImpl::renderBorder(wlr_box* box, const CColor& col, int round) {
|
||||||
RASSERT((box->width > 0 && box->height > 0), "Tried to render rect with width/height < 0!");
|
RASSERT((box->width > 0 && box->height > 0), "Tried to render rect with width/height < 0!");
|
||||||
RASSERT(m_RenderData.pMonitor, "Tried to render rect without begin()!");
|
RASSERT(m_RenderData.pMonitor, "Tried to render rect without begin()!");
|
||||||
|
|
||||||
// this method assumes a set stencil and scaled box
|
static auto *const PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue;
|
||||||
box->x -= thick;
|
static auto *const PMULTISAMPLE = &g_pConfigManager->getConfigValuePtr("decoration:multisample_edges")->intValue;
|
||||||
box->y -= thick;
|
|
||||||
box->width += 2 * thick;
|
|
||||||
box->height += 2 * thick;
|
|
||||||
|
|
||||||
round += thick * m_RenderData.pMonitor->scale; // cuz yeah
|
// adjust box
|
||||||
|
box->x -= *PBORDERSIZE;
|
||||||
|
box->y -= *PBORDERSIZE;
|
||||||
|
box->width += 2 * *PBORDERSIZE;
|
||||||
|
box->height += 2 * *PBORDERSIZE;
|
||||||
|
|
||||||
// only draw on non-stencild.
|
round += *PBORDERSIZE;
|
||||||
glStencilFunc(GL_NOTEQUAL, 1, -1);
|
|
||||||
|
|
||||||
// draw a rounded rect
|
float matrix[9];
|
||||||
renderRect(box, col, round);
|
wlr_matrix_project_box(matrix, box, wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform), 0, m_RenderData.pMonitor->output->transform_matrix); // TODO: write own, don't use WLR here
|
||||||
|
|
||||||
|
float glMatrix[9];
|
||||||
|
wlr_matrix_multiply(glMatrix, m_RenderData.projection, matrix);
|
||||||
|
wlr_matrix_multiply(glMatrix, matrixFlip180, glMatrix);
|
||||||
|
|
||||||
|
wlr_matrix_transpose(glMatrix, glMatrix);
|
||||||
|
|
||||||
|
glEnable(GL_BLEND);
|
||||||
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
|
||||||
|
glUseProgram(m_shBORDER1.program);
|
||||||
|
|
||||||
|
glUniformMatrix3fv(m_shBORDER1.proj, 1, GL_FALSE, glMatrix);
|
||||||
|
glUniform4f(glGetUniformLocation(m_shBORDER1.program, "color"), col.r / 255.f, col.g / 255.f, col.b / 255.f, col.a / 255.f);
|
||||||
|
|
||||||
|
const auto TOPLEFT = Vector2D(round, round);
|
||||||
|
const auto BOTTOMRIGHT = Vector2D(box->width - round, box->height - round);
|
||||||
|
const auto FULLSIZE = Vector2D(box->width, box->height);
|
||||||
|
|
||||||
|
glUniform2f(glGetUniformLocation(m_shBORDER1.program, "topLeft"), (float)TOPLEFT.x, (float)TOPLEFT.y);
|
||||||
|
glUniform2f(glGetUniformLocation(m_shBORDER1.program, "bottomRight"), (float)BOTTOMRIGHT.x, (float)BOTTOMRIGHT.y);
|
||||||
|
glUniform2f(glGetUniformLocation(m_shBORDER1.program, "fullSize"), (float)FULLSIZE.x, (float)FULLSIZE.y);
|
||||||
|
glUniform1f(glGetUniformLocation(m_shBORDER1.program, "radius"), round);
|
||||||
|
glUniform1f(glGetUniformLocation(m_shBORDER1.program, "thick"), *PBORDERSIZE);
|
||||||
|
glUniform1i(glGetUniformLocation(m_shBORDER1.program, "primitiveMultisample"), *PMULTISAMPLE);
|
||||||
|
|
||||||
|
glVertexAttribPointer(m_shBORDER1.posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
|
||||||
|
glVertexAttribPointer(m_shBORDER1.texAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
|
||||||
|
|
||||||
|
glEnableVertexAttribArray(m_shBORDER1.posAttrib);
|
||||||
|
glEnableVertexAttribArray(m_shBORDER1.texAttrib);
|
||||||
|
|
||||||
|
if (pixman_region32_not_empty(m_RenderData.pDamage)) {
|
||||||
|
PIXMAN_DAMAGE_FOREACH(m_RenderData.pDamage) {
|
||||||
|
const auto RECT = RECTSARR[i];
|
||||||
|
scissor(&RECT);
|
||||||
|
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
glDisableVertexAttribArray(m_shBORDER1.posAttrib);
|
||||||
|
glDisableVertexAttribArray(m_shBORDER1.texAttrib);
|
||||||
|
|
||||||
|
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CHyprOpenGLImpl::makeWindowSnapshot(CWindow* pWindow) {
|
void CHyprOpenGLImpl::makeWindowSnapshot(CWindow* pWindow) {
|
||||||
@@ -814,6 +852,68 @@ void CHyprOpenGLImpl::renderSnapshot(SLayerSurface** pLayer) {
|
|||||||
pixman_region32_fini(&fakeDamage);
|
pixman_region32_fini(&fakeDamage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CHyprOpenGLImpl::renderRoundedShadow(wlr_box* box, int round, int range, float a) {
|
||||||
|
RASSERT(m_RenderData.pMonitor, "Tried to render shadow without begin()!");
|
||||||
|
RASSERT((box->width > 0 && box->height > 0), "Tried to render shadow with width/height < 0!");
|
||||||
|
|
||||||
|
static auto *const PSHADOWCOL = &g_pConfigManager->getConfigValuePtr("decoration:col.shadow")->intValue;
|
||||||
|
static auto *const PSHADOWPOWER = &g_pConfigManager->getConfigValuePtr("decoration:shadow_render_power")->intValue;
|
||||||
|
static auto *const PSHADOWIGNOREWINDOW = &g_pConfigManager->getConfigValuePtr("decoration:shadow_ignore_window")->intValue;
|
||||||
|
|
||||||
|
const auto SHADOWPOWER = std::clamp((int)*PSHADOWPOWER, 1, 4);
|
||||||
|
|
||||||
|
const auto col = CColor(*PSHADOWCOL);
|
||||||
|
|
||||||
|
float matrix[9];
|
||||||
|
wlr_matrix_project_box(matrix, box, wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform), 0, m_RenderData.pMonitor->output->transform_matrix); // TODO: write own, don't use WLR here
|
||||||
|
|
||||||
|
float glMatrix[9];
|
||||||
|
wlr_matrix_multiply(glMatrix, m_RenderData.projection, matrix);
|
||||||
|
wlr_matrix_multiply(glMatrix, matrixFlip180, glMatrix);
|
||||||
|
|
||||||
|
wlr_matrix_transpose(glMatrix, glMatrix);
|
||||||
|
|
||||||
|
glEnable(GL_BLEND);
|
||||||
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
|
||||||
|
glUseProgram(m_shSHADOW.program);
|
||||||
|
|
||||||
|
glUniformMatrix3fv(m_shSHADOW.proj, 1, GL_FALSE, glMatrix);
|
||||||
|
glUniform4f(glGetUniformLocation(m_shSHADOW.program, "color"), col.r / 255.f, col.g / 255.f, col.b / 255.f, col.a / 255.f * a);
|
||||||
|
|
||||||
|
const auto TOPLEFT = Vector2D(range + round, range + round);
|
||||||
|
const auto BOTTOMRIGHT = Vector2D(box->width - (range + round), box->height - (range + round));
|
||||||
|
const auto FULLSIZE = Vector2D(box->width, box->height);
|
||||||
|
|
||||||
|
// Rounded corners
|
||||||
|
glUniform2f(glGetUniformLocation(m_shSHADOW.program, "topLeft"), (float)TOPLEFT.x, (float)TOPLEFT.y);
|
||||||
|
glUniform2f(glGetUniformLocation(m_shSHADOW.program, "bottomRight"), (float)BOTTOMRIGHT.x, (float)BOTTOMRIGHT.y);
|
||||||
|
glUniform2f(glGetUniformLocation(m_shSHADOW.program, "fullSize"), (float)FULLSIZE.x, (float)FULLSIZE.y);
|
||||||
|
glUniform1f(glGetUniformLocation(m_shSHADOW.program, "radius"), range + round);
|
||||||
|
glUniform1f(glGetUniformLocation(m_shSHADOW.program, "range"), range);
|
||||||
|
glUniform1f(glGetUniformLocation(m_shSHADOW.program, "shadowPower"), SHADOWPOWER);
|
||||||
|
glUniform1i(glGetUniformLocation(m_shSHADOW.program, "ignoreWindow"), *PSHADOWIGNOREWINDOW);
|
||||||
|
|
||||||
|
glVertexAttribPointer(m_shSHADOW.posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
|
||||||
|
glVertexAttribPointer(m_shSHADOW.texAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
|
||||||
|
|
||||||
|
glEnableVertexAttribArray(m_shSHADOW.posAttrib);
|
||||||
|
glEnableVertexAttribArray(m_shSHADOW.texAttrib);
|
||||||
|
|
||||||
|
if (pixman_region32_not_empty(m_RenderData.pDamage)) {
|
||||||
|
PIXMAN_DAMAGE_FOREACH(m_RenderData.pDamage) {
|
||||||
|
const auto RECT = RECTSARR[i];
|
||||||
|
scissor(&RECT);
|
||||||
|
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
glDisableVertexAttribArray(m_shSHADOW.posAttrib);
|
||||||
|
glDisableVertexAttribArray(m_shSHADOW.texAttrib);
|
||||||
|
|
||||||
|
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
}
|
||||||
|
|
||||||
void CHyprOpenGLImpl::createBGTextureForMonitor(SMonitor* pMonitor) {
|
void CHyprOpenGLImpl::createBGTextureForMonitor(SMonitor* pMonitor) {
|
||||||
RASSERT(m_RenderData.pMonitor, "Tried to createBGTex without begin()!");
|
RASSERT(m_RenderData.pMonitor, "Tried to createBGTex without begin()!");
|
||||||
|
|
||||||
|
@@ -34,6 +34,10 @@ struct SCurrentRenderData {
|
|||||||
float projection[9];
|
float projection[9];
|
||||||
|
|
||||||
pixman_region32_t* pDamage = nullptr;
|
pixman_region32_t* pDamage = nullptr;
|
||||||
|
|
||||||
|
bool renderingPrimarySurface = false;
|
||||||
|
Vector2D primarySurfaceUVTopLeft = Vector2D(-1, -1);
|
||||||
|
Vector2D primarySurfaceUVBottomRight = Vector2D(-1, -1);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SMonitorRenderData {
|
struct SMonitorRenderData {
|
||||||
@@ -53,9 +57,12 @@ public:
|
|||||||
void end();
|
void end();
|
||||||
|
|
||||||
void renderRect(wlr_box*, const CColor&, int round = 0);
|
void renderRect(wlr_box*, const CColor&, int round = 0);
|
||||||
|
void renderRectWithDamage(wlr_box*, const CColor&, pixman_region32_t* damage, int round = 0);
|
||||||
void renderTexture(wlr_texture*, wlr_box*, float a, int round = 0);
|
void renderTexture(wlr_texture*, wlr_box*, float a, int round = 0);
|
||||||
void renderTexture(const CTexture&, wlr_box*, float a, int round = 0, bool discardOpaque = false, bool border = false);
|
void renderTexture(const CTexture&, wlr_box*, float a, int round = 0, bool discardOpaque = false, bool allowPrimary = false);
|
||||||
void renderTextureWithBlur(const CTexture&, wlr_box*, float a, wlr_surface* pSurface, int round = 0, bool border = false);
|
void renderTextureWithBlur(const CTexture&, wlr_box*, float a, wlr_surface* pSurface, int round = 0);
|
||||||
|
void renderRoundedShadow(wlr_box*, int round, int range, float a = 1.0);
|
||||||
|
void renderBorder(wlr_box*, const CColor&, int round);
|
||||||
|
|
||||||
void makeWindowSnapshot(CWindow*);
|
void makeWindowSnapshot(CWindow*);
|
||||||
void makeLayerSnapshot(SLayerSurface*);
|
void makeLayerSnapshot(SLayerSurface*);
|
||||||
@@ -101,6 +108,8 @@ private:
|
|||||||
CShader m_shEXT;
|
CShader m_shEXT;
|
||||||
CShader m_shBLUR1;
|
CShader m_shBLUR1;
|
||||||
CShader m_shBLUR2;
|
CShader m_shBLUR2;
|
||||||
|
CShader m_shSHADOW;
|
||||||
|
CShader m_shBORDER1;
|
||||||
//
|
//
|
||||||
|
|
||||||
GLuint createProgram(const std::string&, const std::string&);
|
GLuint createProgram(const std::string&, const std::string&);
|
||||||
@@ -110,8 +119,7 @@ private:
|
|||||||
// returns the out FB, can be either Mirror or MirrorSwap
|
// returns the out FB, can be either Mirror or MirrorSwap
|
||||||
CFramebuffer* blurMainFramebufferWithDamage(float a, wlr_box* pBox, pixman_region32_t* damage);
|
CFramebuffer* blurMainFramebufferWithDamage(float a, wlr_box* pBox, pixman_region32_t* damage);
|
||||||
|
|
||||||
void renderTextureInternalWithDamage(const CTexture&, wlr_box* pBox, float a, pixman_region32_t* damage, int round = 0, bool discardOpaque = false, bool border = false, bool noAA = false);
|
void renderTextureInternalWithDamage(const CTexture&, wlr_box* pBox, float a, pixman_region32_t* damage, int round = 0, bool discardOpaque = false, bool noAA = false, bool allowPrimary = false);
|
||||||
void renderBorder(wlr_box*, const CColor&, int thick = 1, int round = 0);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
inline std::unique_ptr<CHyprOpenGLImpl> g_pHyprOpenGL;
|
inline std::unique_ptr<CHyprOpenGLImpl> g_pHyprOpenGL;
|
@@ -19,10 +19,22 @@ void renderSurface(struct wlr_surface* surface, int x, int y, void* data) {
|
|||||||
}
|
}
|
||||||
scaleBox(&windowBox, RDATA->output->scale);
|
scaleBox(&windowBox, RDATA->output->scale);
|
||||||
|
|
||||||
float rounding = RDATA->dontRound ? 0 : RDATA->rounding == -1 ? g_pConfigManager->getInt("decoration:rounding") : RDATA->rounding;
|
static auto *const PROUNDING = &g_pConfigManager->getConfigValuePtr("decoration:rounding")->intValue;
|
||||||
|
|
||||||
if (RDATA->surface && surface == RDATA->surface)
|
float rounding = RDATA->dontRound ? 0 : RDATA->rounding == -1 ? *PROUNDING : RDATA->rounding;
|
||||||
g_pHyprOpenGL->renderTextureWithBlur(TEXTURE, &windowBox, RDATA->fadeAlpha * RDATA->alpha, surface, rounding, RDATA->decorate);
|
|
||||||
|
g_pHyprOpenGL->m_RenderData.renderingPrimarySurface = false;
|
||||||
|
|
||||||
|
if (RDATA->surface && surface == RDATA->surface) {
|
||||||
|
g_pHyprOpenGL->m_RenderData.renderingPrimarySurface = true;
|
||||||
|
g_pHyprOpenGL->renderTextureWithBlur(TEXTURE, &windowBox, RDATA->fadeAlpha * RDATA->alpha, surface, rounding);
|
||||||
|
|
||||||
|
if (RDATA->decorate) {
|
||||||
|
auto col = g_pHyprOpenGL->m_pCurrentWindow->m_cRealBorderColor.col();
|
||||||
|
col.a *= RDATA->fadeAlpha * RDATA->alpha / 255.f;
|
||||||
|
g_pHyprOpenGL->renderBorder(&windowBox, col, rounding);
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
g_pHyprOpenGL->renderTexture(TEXTURE, &windowBox, RDATA->fadeAlpha * RDATA->alpha, rounding, false, false);
|
g_pHyprOpenGL->renderTexture(TEXTURE, &windowBox, RDATA->fadeAlpha * RDATA->alpha, rounding, false, false);
|
||||||
|
|
||||||
@@ -140,6 +152,8 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, SMonitor* pMonitor, timespec*
|
|||||||
|
|
||||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID);
|
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID);
|
||||||
const auto REALPOS = pWindow->m_vRealPosition.vec() + PWORKSPACE->m_vRenderOffset.vec();
|
const auto REALPOS = pWindow->m_vRealPosition.vec() + PWORKSPACE->m_vRenderOffset.vec();
|
||||||
|
static const auto PNOFLOATINGBORDERS = &g_pConfigManager->getConfigValuePtr("general:no_border_on_floating")->intValue;
|
||||||
|
|
||||||
SRenderData renderdata = {pMonitor->output, time, REALPOS.x, REALPOS.y};
|
SRenderData renderdata = {pMonitor->output, time, REALPOS.x, REALPOS.y};
|
||||||
renderdata.surface = g_pXWaylandManager->getWindowSurface(pWindow);
|
renderdata.surface = g_pXWaylandManager->getWindowSurface(pWindow);
|
||||||
renderdata.w = std::clamp(pWindow->m_vRealSize.vec().x, (double)5, (double)1337420); // clamp the size to min 5,
|
renderdata.w = std::clamp(pWindow->m_vRealSize.vec().x, (double)5, (double)1337420); // clamp the size to min 5,
|
||||||
@@ -147,7 +161,7 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, SMonitor* pMonitor, timespec*
|
|||||||
renderdata.dontRound = pWindow->m_bIsFullscreen && PWORKSPACE->m_efFullscreenMode == FULLSCREEN_FULL;
|
renderdata.dontRound = pWindow->m_bIsFullscreen && PWORKSPACE->m_efFullscreenMode == FULLSCREEN_FULL;
|
||||||
renderdata.fadeAlpha = pWindow->m_fAlpha.fl() * (PWORKSPACE->m_fAlpha.fl() / 255.f);
|
renderdata.fadeAlpha = pWindow->m_fAlpha.fl() * (PWORKSPACE->m_fAlpha.fl() / 255.f);
|
||||||
renderdata.alpha = pWindow->m_bIsFullscreen ? g_pConfigManager->getFloat("decoration:fullscreen_opacity") : pWindow == g_pCompositor->m_pLastWindow ? g_pConfigManager->getFloat("decoration:active_opacity") : g_pConfigManager->getFloat("decoration:inactive_opacity");
|
renderdata.alpha = pWindow->m_bIsFullscreen ? g_pConfigManager->getFloat("decoration:fullscreen_opacity") : pWindow == g_pCompositor->m_pLastWindow ? g_pConfigManager->getFloat("decoration:active_opacity") : g_pConfigManager->getFloat("decoration:inactive_opacity");
|
||||||
renderdata.decorate = decorate && !pWindow->m_bX11DoesntWantBorders;
|
renderdata.decorate = decorate && !pWindow->m_bX11DoesntWantBorders && (pWindow->m_bIsFloating ? *PNOFLOATINGBORDERS == 0 : true);
|
||||||
renderdata.rounding = pWindow->m_sAdditionalConfigData.rounding;
|
renderdata.rounding = pWindow->m_sAdditionalConfigData.rounding;
|
||||||
|
|
||||||
// apply window special data
|
// apply window special data
|
||||||
@@ -160,16 +174,33 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, SMonitor* pMonitor, timespec*
|
|||||||
|
|
||||||
// render window decorations first
|
// render window decorations first
|
||||||
for (auto& wd : pWindow->m_dWindowDecorations)
|
for (auto& wd : pWindow->m_dWindowDecorations)
|
||||||
wd->draw(pMonitor);
|
wd->draw(pMonitor, renderdata.alpha * renderdata.fadeAlpha / 255.f);
|
||||||
|
|
||||||
|
if (!pWindow->m_bIsX11) {
|
||||||
|
|
||||||
|
// To everyone who makes apps with improperly aligned surfaces,
|
||||||
|
// For example chromium, or GTK devs who allow shadows on windows,
|
||||||
|
// a sincere FUCK YOU.
|
||||||
|
|
||||||
|
wlr_box geom;
|
||||||
|
wlr_xdg_surface_get_geometry(pWindow->m_uSurface.xdg, &geom);
|
||||||
|
|
||||||
|
g_pHyprOpenGL->m_RenderData.primarySurfaceUVTopLeft = Vector2D((double)geom.x / (double)pWindow->m_uSurface.xdg->surface->current.width, (double)geom.y / (double)pWindow->m_uSurface.xdg->surface->current.height);
|
||||||
|
g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight = Vector2D((double)(geom.width + geom.x) / (double)pWindow->m_uSurface.xdg->surface->current.width, (double)(geom.y + geom.height) / (double)pWindow->m_uSurface.xdg->surface->current.height);
|
||||||
|
|
||||||
|
if (g_pHyprOpenGL->m_RenderData.primarySurfaceUVTopLeft == Vector2D() && g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight == Vector2D(1, 1)) {
|
||||||
|
// No special UV mods needed
|
||||||
|
g_pHyprOpenGL->m_RenderData.primarySurfaceUVTopLeft = Vector2D(-1, -1);
|
||||||
|
g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight = Vector2D(-1, -1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
wlr_surface_for_each_surface(g_pXWaylandManager->getWindowSurface(pWindow), renderSurface, &renderdata);
|
wlr_surface_for_each_surface(g_pXWaylandManager->getWindowSurface(pWindow), renderSurface, &renderdata);
|
||||||
|
|
||||||
if (pWindow->m_bIsX11) {
|
g_pHyprOpenGL->m_RenderData.primarySurfaceUVTopLeft = Vector2D(-1, -1);
|
||||||
if (pWindow->m_uSurface.xwayland->surface) {
|
g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight = Vector2D(-1, -1);
|
||||||
wlr_surface_for_each_surface(pWindow->m_uSurface.xwayland->surface, renderSurface, &renderdata);
|
|
||||||
}
|
if (!pWindow->m_bIsX11) {
|
||||||
}
|
|
||||||
else {
|
|
||||||
renderdata.dontRound = false; // restore dontround
|
renderdata.dontRound = false; // restore dontround
|
||||||
renderdata.pMonitor = pMonitor;
|
renderdata.pMonitor = pMonitor;
|
||||||
wlr_xdg_surface_for_each_popup_surface(pWindow->m_uSurface.xdg, renderSurface, &renderdata);
|
wlr_xdg_surface_for_each_popup_surface(pWindow->m_uSurface.xdg, renderSurface, &renderdata);
|
||||||
@@ -533,7 +564,9 @@ void CHyprRenderer::damageSurface(wlr_surface* pSurface, double x, double y) {
|
|||||||
|
|
||||||
pixman_region32_fini(&damageBox);
|
pixman_region32_fini(&damageBox);
|
||||||
|
|
||||||
if (g_pConfigManager->getInt("debug:log_damage"))
|
static auto *const PLOGDAMAGE = &g_pConfigManager->getConfigValuePtr("debug:log_damage")->intValue;
|
||||||
|
|
||||||
|
if (*PLOGDAMAGE)
|
||||||
Debug::log(LOG, "Damage: Surface (extents): xy: %d, %d wh: %d, %d", damageBox.extents.x1, damageBox.extents.y1, damageBox.extents.x2 - damageBox.extents.x1, damageBox.extents.y2 - damageBox.extents.y1);
|
Debug::log(LOG, "Damage: Surface (extents): xy: %d, %d wh: %d, %d", damageBox.extents.x1, damageBox.extents.y1, damageBox.extents.x2 - damageBox.extents.x1, damageBox.extents.y2 - damageBox.extents.y1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -542,7 +575,7 @@ void CHyprRenderer::damageWindow(CWindow* pWindow) {
|
|||||||
// damage by size & pos
|
// damage by size & pos
|
||||||
// TODO TEMP: revise when added shadows/etc
|
// TODO TEMP: revise when added shadows/etc
|
||||||
|
|
||||||
wlr_box damageBox = {pWindow->m_vRealPosition.vec().x, pWindow->m_vRealPosition.vec().y, pWindow->m_vRealSize.vec().x, pWindow->m_vRealSize.vec().y};
|
wlr_box damageBox = pWindow->getFullWindowBoundingBox();
|
||||||
for (auto& m : g_pCompositor->m_lMonitors) {
|
for (auto& m : g_pCompositor->m_lMonitors) {
|
||||||
wlr_box fixedDamageBox = damageBox;
|
wlr_box fixedDamageBox = damageBox;
|
||||||
fixedDamageBox.x -= m.vecPosition.x;
|
fixedDamageBox.x -= m.vecPosition.x;
|
||||||
@@ -551,12 +584,13 @@ void CHyprRenderer::damageWindow(CWindow* pWindow) {
|
|||||||
wlr_output_damage_add_box(m.damage, &fixedDamageBox);
|
wlr_output_damage_add_box(m.damage, &fixedDamageBox);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (g_pConfigManager->getInt("debug:log_damage"))
|
static auto *const PLOGDAMAGE = &g_pConfigManager->getConfigValuePtr("debug:log_damage")->intValue;
|
||||||
|
|
||||||
|
if (*PLOGDAMAGE)
|
||||||
Debug::log(LOG, "Damage: Window floated (%s): xy: %d, %d wh: %d, %d", pWindow->m_szTitle.c_str(), damageBox.x, damageBox.y, damageBox.width, damageBox.height);
|
Debug::log(LOG, "Damage: Window floated (%s): xy: %d, %d wh: %d, %d", pWindow->m_szTitle.c_str(), damageBox.x, damageBox.y, damageBox.width, damageBox.height);
|
||||||
} else {
|
} else {
|
||||||
// damage by real size & pos + border size * 2 (JIC)
|
// damage by real size & pos + border size * 2 (JIC)
|
||||||
const auto BORDERSIZE = g_pConfigManager->getInt("general:border_size");
|
wlr_box damageBox = pWindow->getFullWindowBoundingBox();
|
||||||
wlr_box damageBox = { pWindow->m_vRealPosition.vec().x - BORDERSIZE - 1, pWindow->m_vRealPosition.vec().y - BORDERSIZE - 1, pWindow->m_vRealSize.vec().x + 2 * BORDERSIZE + 2, pWindow->m_vRealSize.vec().y + 2 * BORDERSIZE + 2};
|
|
||||||
for (auto& m : g_pCompositor->m_lMonitors) {
|
for (auto& m : g_pCompositor->m_lMonitors) {
|
||||||
wlr_box fixedDamageBox = damageBox;
|
wlr_box fixedDamageBox = damageBox;
|
||||||
fixedDamageBox.x -= m.vecPosition.x;
|
fixedDamageBox.x -= m.vecPosition.x;
|
||||||
@@ -565,7 +599,9 @@ void CHyprRenderer::damageWindow(CWindow* pWindow) {
|
|||||||
wlr_output_damage_add_box(m.damage, &fixedDamageBox);
|
wlr_output_damage_add_box(m.damage, &fixedDamageBox);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (g_pConfigManager->getInt("debug:log_damage"))
|
static auto *const PLOGDAMAGE = &g_pConfigManager->getConfigValuePtr("debug:log_damage")->intValue;
|
||||||
|
|
||||||
|
if (*PLOGDAMAGE)
|
||||||
Debug::log(LOG, "Damage: Window tiled (%s): xy: %d, %d wh: %d, %d", pWindow->m_szTitle.c_str(), damageBox.x, damageBox.y, damageBox.width, damageBox.height);
|
Debug::log(LOG, "Damage: Window tiled (%s): xy: %d, %d wh: %d, %d", pWindow->m_szTitle.c_str(), damageBox.x, damageBox.y, damageBox.width, damageBox.height);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -574,7 +610,9 @@ void CHyprRenderer::damageMonitor(SMonitor* pMonitor) {
|
|||||||
wlr_box damageBox = {0, 0, pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y};
|
wlr_box damageBox = {0, 0, pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y};
|
||||||
wlr_output_damage_add_box(pMonitor->damage, &damageBox);
|
wlr_output_damage_add_box(pMonitor->damage, &damageBox);
|
||||||
|
|
||||||
if (g_pConfigManager->getInt("debug:log_damage"))
|
static auto *const PLOGDAMAGE = &g_pConfigManager->getConfigValuePtr("debug:log_damage")->intValue;
|
||||||
|
|
||||||
|
if (*PLOGDAMAGE)
|
||||||
Debug::log(LOG, "Damage: Monitor %s", pMonitor->szName.c_str());
|
Debug::log(LOG, "Damage: Monitor %s", pMonitor->szName.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -585,7 +623,9 @@ void CHyprRenderer::damageBox(wlr_box* pBox) {
|
|||||||
wlr_output_damage_add_box(m.damage, &damageBox);
|
wlr_output_damage_add_box(m.damage, &damageBox);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (g_pConfigManager->getInt("debug:log_damage"))
|
static auto *const PLOGDAMAGE = &g_pConfigManager->getConfigValuePtr("debug:log_damage")->intValue;
|
||||||
|
|
||||||
|
if (*PLOGDAMAGE)
|
||||||
Debug::log(LOG, "Damage: Box: xy: %d, %d wh: %d, %d", pBox->x, pBox->y, pBox->width, pBox->height);
|
Debug::log(LOG, "Damage: Box: xy: %d, %d wh: %d, %d", pBox->x, pBox->y, pBox->width, pBox->height);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -719,3 +759,38 @@ void CHyprRenderer::applyMonitorRule(SMonitor* pMonitor, SMonitorRule* pMonitorR
|
|||||||
// frame skip
|
// frame skip
|
||||||
pMonitor->framesToSkip = 1;
|
pMonitor->framesToSkip = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CHyprRenderer::ensureCursorRenderingMode() {
|
||||||
|
static auto *const PCURSORTIMEOUT = &g_pConfigManager->getConfigValuePtr("general:cursor_inactive_timeout")->intValue;
|
||||||
|
|
||||||
|
const auto PASSEDCURSORSECONDS = g_pInputManager->m_tmrLastCursorMovement.getSeconds();
|
||||||
|
|
||||||
|
if (*PCURSORTIMEOUT > 0) {
|
||||||
|
if (*PCURSORTIMEOUT < PASSEDCURSORSECONDS && m_bHasARenderedCursor) {
|
||||||
|
m_bHasARenderedCursor = false;
|
||||||
|
|
||||||
|
wlr_cursor_set_surface(g_pCompositor->m_sWLRCursor, nullptr, 0, 0); // hide
|
||||||
|
|
||||||
|
Debug::log(LOG, "Hiding the cursor (timeout)");
|
||||||
|
|
||||||
|
for (auto& m : g_pCompositor->m_lMonitors)
|
||||||
|
g_pHyprRenderer->damageMonitor(&m); // TODO: maybe just damage the cursor area?
|
||||||
|
} else if (*PCURSORTIMEOUT > PASSEDCURSORSECONDS && !m_bHasARenderedCursor) {
|
||||||
|
m_bHasARenderedCursor = true;
|
||||||
|
|
||||||
|
if (!m_bWindowRequestedCursorHide)
|
||||||
|
wlr_xcursor_manager_set_cursor_image(g_pCompositor->m_sWLRXCursorMgr, "left_ptr", g_pCompositor->m_sWLRCursor);
|
||||||
|
|
||||||
|
Debug::log(LOG, "Showing the cursor (timeout)");
|
||||||
|
|
||||||
|
for (auto& m : g_pCompositor->m_lMonitors)
|
||||||
|
g_pHyprRenderer->damageMonitor(&m); // TODO: maybe just damage the cursor area?
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
m_bHasARenderedCursor = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CHyprRenderer::shouldRenderCursor() {
|
||||||
|
return m_bHasARenderedCursor;
|
||||||
|
}
|
@@ -31,6 +31,10 @@ public:
|
|||||||
void applyMonitorRule(SMonitor*, SMonitorRule*, bool force = false);
|
void applyMonitorRule(SMonitor*, SMonitorRule*, bool force = false);
|
||||||
bool shouldRenderWindow(CWindow*, SMonitor*);
|
bool shouldRenderWindow(CWindow*, SMonitor*);
|
||||||
bool shouldRenderWindow(CWindow*);
|
bool shouldRenderWindow(CWindow*);
|
||||||
|
void ensureCursorRenderingMode();
|
||||||
|
bool shouldRenderCursor();
|
||||||
|
|
||||||
|
bool m_bWindowRequestedCursorHide = false;
|
||||||
|
|
||||||
DAMAGETRACKINGMODES damageTrackingModeFromStr(const std::string&);
|
DAMAGETRACKINGMODES damageTrackingModeFromStr(const std::string&);
|
||||||
|
|
||||||
@@ -41,6 +45,8 @@ private:
|
|||||||
void renderLayer(SLayerSurface*, SMonitor*, timespec*);
|
void renderLayer(SLayerSurface*, SMonitor*, timespec*);
|
||||||
void renderDragIcon(SMonitor*, timespec*);
|
void renderDragIcon(SMonitor*, timespec*);
|
||||||
|
|
||||||
|
bool m_bHasARenderedCursor = true;
|
||||||
|
|
||||||
|
|
||||||
friend class CHyprOpenGLImpl;
|
friend class CHyprOpenGLImpl;
|
||||||
};
|
};
|
||||||
|
@@ -1,341 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <string>
|
#include "shaders/Textures.hpp"
|
||||||
|
#include "shaders/Shadow.hpp"
|
||||||
inline static constexpr auto ROUNDED_SHADER_FUNC = [](const std::string colorVarName) -> std::string {
|
#include "shaders/Border.hpp"
|
||||||
return R"#(
|
|
||||||
if (pixCoord[0] < topLeft[0]) {
|
|
||||||
// we're close left
|
|
||||||
if (pixCoord[1] < topLeft[1]) {
|
|
||||||
// top
|
|
||||||
|
|
||||||
if (ignoreCorners == 1) {
|
|
||||||
discard;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
float topLeftDistance = distance(topLeft, pixCoord);
|
|
||||||
|
|
||||||
if (topLeftDistance > radius - 1.0) {
|
|
||||||
if (primitiveMultisample == 0 && topLeftDistance > radius) {
|
|
||||||
discard;
|
|
||||||
return;
|
|
||||||
} else if (primitiveMultisample == 1) {
|
|
||||||
float distances = 0.0;
|
|
||||||
if (distance(topLeft, pixCoord + vec2(0.25, 0.25)) < radius) { distances = distances + 1.0; }
|
|
||||||
if (distance(topLeft, pixCoord + vec2(0.75, 0.25)) < radius) { distances = distances + 1.0; }
|
|
||||||
if (distance(topLeft, pixCoord + vec2(0.25, 0.75)) < radius) { distances = distances + 1.0; }
|
|
||||||
if (distance(topLeft, pixCoord + vec2(0.75, 0.75)) < radius) { distances = distances + 1.0; }
|
|
||||||
|
|
||||||
if (distances == 0.0) {
|
|
||||||
discard;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
distances = distances / 4.0;
|
|
||||||
|
|
||||||
gl_FragColor = )#" + colorVarName + R"#( * distances;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (pixCoord[1] > bottomRight[1]) {
|
|
||||||
// bottom
|
|
||||||
|
|
||||||
if (ignoreCorners == 1) {
|
|
||||||
discard;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
float topLeftDistance = distance(vec2(topLeft[0], bottomRight[1]), pixCoord);
|
|
||||||
|
|
||||||
if (topLeftDistance > radius - 1.0) {
|
|
||||||
if (primitiveMultisample == 0 && topLeftDistance > radius) {
|
|
||||||
discard;
|
|
||||||
return;
|
|
||||||
} else if (primitiveMultisample == 1) {
|
|
||||||
float distances = 0.0;
|
|
||||||
if (distance(vec2(topLeft[0], bottomRight[1]), pixCoord + vec2(0.25, 0.25)) < radius) { distances = distances + 1.0; }
|
|
||||||
if (distance(vec2(topLeft[0], bottomRight[1]), pixCoord + vec2(0.75, 0.25)) < radius) { distances = distances + 1.0; }
|
|
||||||
if (distance(vec2(topLeft[0], bottomRight[1]), pixCoord + vec2(0.25, 0.75)) < radius) { distances = distances + 1.0; }
|
|
||||||
if (distance(vec2(topLeft[0], bottomRight[1]), pixCoord + vec2(0.75, 0.75)) < radius) { distances = distances + 1.0; }
|
|
||||||
|
|
||||||
if (distances == 0.0) {
|
|
||||||
discard;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
distances = distances / 4.0;
|
|
||||||
|
|
||||||
gl_FragColor = )#" + colorVarName + R"#( * distances;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (pixCoord[0] > bottomRight[0]) {
|
|
||||||
// we're close right
|
|
||||||
if (pixCoord[1] < topLeft[1]) {
|
|
||||||
// top
|
|
||||||
|
|
||||||
if (ignoreCorners == 1) {
|
|
||||||
discard;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
float topLeftDistance = distance(vec2(bottomRight[0], topLeft[1]), pixCoord);
|
|
||||||
|
|
||||||
if (topLeftDistance > radius - 1.0) {
|
|
||||||
if (primitiveMultisample == 0 && topLeftDistance > radius) {
|
|
||||||
discard;
|
|
||||||
return;
|
|
||||||
} else if (primitiveMultisample == 1) {
|
|
||||||
float distances = 0.0;
|
|
||||||
if (distance(vec2(bottomRight[0], topLeft[1]), pixCoord + vec2(0.25, 0.25)) < radius) { distances = distances + 1.0; }
|
|
||||||
if (distance(vec2(bottomRight[0], topLeft[1]), pixCoord + vec2(0.75, 0.25)) < radius) { distances = distances + 1.0; }
|
|
||||||
if (distance(vec2(bottomRight[0], topLeft[1]), pixCoord + vec2(0.25, 0.75)) < radius) { distances = distances + 1.0; }
|
|
||||||
if (distance(vec2(bottomRight[0], topLeft[1]), pixCoord + vec2(0.75, 0.75)) < radius) { distances = distances + 1.0; }
|
|
||||||
|
|
||||||
if (distances == 0.0) {
|
|
||||||
discard;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
distances = distances / 4.0;
|
|
||||||
|
|
||||||
gl_FragColor = )#" + colorVarName + R"#( * distances;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (pixCoord[1] > bottomRight[1]) {
|
|
||||||
// bottom
|
|
||||||
|
|
||||||
if (ignoreCorners == 1) {
|
|
||||||
discard;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
float topLeftDistance = distance(bottomRight, pixCoord);
|
|
||||||
|
|
||||||
if (topLeftDistance > radius - 1.0) {
|
|
||||||
if (primitiveMultisample == 0 && topLeftDistance > radius) {
|
|
||||||
discard;
|
|
||||||
return;
|
|
||||||
} else if (primitiveMultisample == 1) {
|
|
||||||
float distances = 0.0;
|
|
||||||
if (distance(bottomRight, pixCoord + vec2(0.25, 0.25)) < radius) { distances = distances + 1.0; }
|
|
||||||
if (distance(bottomRight, pixCoord + vec2(0.75, 0.25)) < radius) { distances = distances + 1.0; }
|
|
||||||
if (distance(bottomRight, pixCoord + vec2(0.25, 0.75)) < radius) { distances = distances + 1.0; }
|
|
||||||
if (distance(bottomRight, pixCoord + vec2(0.75, 0.75)) < radius) { distances = distances + 1.0; }
|
|
||||||
|
|
||||||
if (distances == 0.0) {
|
|
||||||
discard;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
distances = distances / 4.0;
|
|
||||||
|
|
||||||
gl_FragColor = )#" + colorVarName + R"#( * distances;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)#";
|
|
||||||
};
|
|
||||||
|
|
||||||
inline const std::string QUADVERTSRC = R"#(
|
|
||||||
uniform mat3 proj;
|
|
||||||
uniform vec4 color;
|
|
||||||
attribute vec2 pos;
|
|
||||||
attribute vec2 texcoord;
|
|
||||||
varying vec4 v_color;
|
|
||||||
varying vec2 v_texcoord;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
gl_Position = vec4(proj * vec3(pos, 1.0), 1.0);
|
|
||||||
v_color = color;
|
|
||||||
v_texcoord = texcoord;
|
|
||||||
})#";
|
|
||||||
|
|
||||||
inline const std::string QUADFRAGSRC = R"#(
|
|
||||||
precision mediump float;
|
|
||||||
varying vec4 v_color;
|
|
||||||
varying vec2 v_texcoord;
|
|
||||||
|
|
||||||
uniform vec2 topLeft;
|
|
||||||
uniform vec2 bottomRight;
|
|
||||||
uniform vec2 fullSize;
|
|
||||||
uniform float radius;
|
|
||||||
|
|
||||||
uniform int primitiveMultisample;
|
|
||||||
uniform int ignoreCorners;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
if (radius == 0.0) {
|
|
||||||
gl_FragColor = v_color;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
vec2 pixCoord = fullSize * v_texcoord;
|
|
||||||
|
|
||||||
)#" + ROUNDED_SHADER_FUNC("v_color") + R"#(
|
|
||||||
|
|
||||||
gl_FragColor = v_color;
|
|
||||||
})#";
|
|
||||||
|
|
||||||
inline const std::string TEXVERTSRC = R"#(
|
|
||||||
uniform mat3 proj;
|
|
||||||
attribute vec2 pos;
|
|
||||||
attribute vec2 texcoord;
|
|
||||||
varying vec2 v_texcoord;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
gl_Position = vec4(proj * vec3(pos, 1.0), 1.0);
|
|
||||||
v_texcoord = texcoord;
|
|
||||||
})#";
|
|
||||||
|
|
||||||
inline const std::string TEXFRAGSRCRGBA = R"#(
|
|
||||||
precision mediump float;
|
|
||||||
varying vec2 v_texcoord; // is in 0-1
|
|
||||||
uniform sampler2D tex;
|
|
||||||
uniform float alpha;
|
|
||||||
|
|
||||||
uniform vec2 topLeft;
|
|
||||||
uniform vec2 bottomRight;
|
|
||||||
uniform vec2 fullSize;
|
|
||||||
uniform float radius;
|
|
||||||
|
|
||||||
uniform int discardOpaque;
|
|
||||||
|
|
||||||
uniform int primitiveMultisample;
|
|
||||||
uniform int ignoreCorners;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
|
|
||||||
vec4 pixColor = texture2D(tex, v_texcoord);
|
|
||||||
|
|
||||||
if (discardOpaque == 1 && pixColor[3] * alpha == 1.0) {
|
|
||||||
discard;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
vec2 pixCoord = fullSize * v_texcoord;
|
|
||||||
|
|
||||||
)#" + ROUNDED_SHADER_FUNC("pixColor") +
|
|
||||||
R"#(
|
|
||||||
|
|
||||||
gl_FragColor = pixColor * alpha;
|
|
||||||
})#";
|
|
||||||
|
|
||||||
inline const std::string TEXFRAGSRCRGBX = R"#(
|
|
||||||
precision mediump float;
|
|
||||||
varying vec2 v_texcoord;
|
|
||||||
uniform sampler2D tex;
|
|
||||||
uniform float alpha;
|
|
||||||
|
|
||||||
uniform vec2 topLeft;
|
|
||||||
uniform vec2 bottomRight;
|
|
||||||
uniform vec2 fullSize;
|
|
||||||
uniform float radius;
|
|
||||||
|
|
||||||
uniform int discardOpaque;
|
|
||||||
|
|
||||||
uniform int primitiveMultisample;
|
|
||||||
uniform int ignoreCorners;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
|
|
||||||
if (discardOpaque == 1 && alpha == 1.0) {
|
|
||||||
discard;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
vec4 pixColor = vec4(texture2D(tex, v_texcoord).rgb, 1.0);
|
|
||||||
|
|
||||||
vec2 pixCoord = fullSize * v_texcoord;
|
|
||||||
|
|
||||||
)#" + ROUNDED_SHADER_FUNC("pixColor") + R"#(
|
|
||||||
|
|
||||||
gl_FragColor = pixColor * alpha;
|
|
||||||
})#";
|
|
||||||
|
|
||||||
inline const std::string FRAGBLUR1 = R"#(
|
|
||||||
#version 100
|
|
||||||
precision mediump float;
|
|
||||||
varying mediump vec2 v_texcoord; // is in 0-1
|
|
||||||
uniform sampler2D tex;
|
|
||||||
|
|
||||||
uniform float radius;
|
|
||||||
uniform vec2 halfpixel;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
vec2 uv = v_texcoord * 2.0;
|
|
||||||
|
|
||||||
vec4 sum = texture2D(tex, uv) * 4.0;
|
|
||||||
sum += texture2D(tex, uv - halfpixel.xy * radius);
|
|
||||||
sum += texture2D(tex, uv + halfpixel.xy * radius);
|
|
||||||
sum += texture2D(tex, uv + vec2(halfpixel.x, -halfpixel.y) * radius);
|
|
||||||
sum += texture2D(tex, uv - vec2(halfpixel.x, -halfpixel.y) * radius);
|
|
||||||
gl_FragColor = sum / 8.0;
|
|
||||||
}
|
|
||||||
)#";
|
|
||||||
|
|
||||||
inline const std::string FRAGBLUR2 = R"#(
|
|
||||||
#version 100
|
|
||||||
precision mediump float;
|
|
||||||
varying mediump vec2 v_texcoord; // is in 0-1
|
|
||||||
uniform sampler2D tex;
|
|
||||||
|
|
||||||
uniform float radius;
|
|
||||||
uniform vec2 halfpixel;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
vec2 uv = v_texcoord / 2.0;
|
|
||||||
|
|
||||||
vec4 sum = texture2D(tex, uv + vec2(-halfpixel.x * 2.0, 0.0) * radius);
|
|
||||||
|
|
||||||
sum += texture2D(tex, uv + vec2(-halfpixel.x, halfpixel.y) * radius) * 2.0;
|
|
||||||
sum += texture2D(tex, uv + vec2(0.0, halfpixel.y * 2.0) * radius);
|
|
||||||
sum += texture2D(tex, uv + vec2(halfpixel.x, halfpixel.y) * radius) * 2.0;
|
|
||||||
sum += texture2D(tex, uv + vec2(halfpixel.x * 2.0, 0.0) * radius);
|
|
||||||
sum += texture2D(tex, uv + vec2(halfpixel.x, -halfpixel.y) * radius) * 2.0;
|
|
||||||
sum += texture2D(tex, uv + vec2(0.0, -halfpixel.y * 2.0) * radius);
|
|
||||||
sum += texture2D(tex, uv + vec2(-halfpixel.x, -halfpixel.y) * radius) * 2.0;
|
|
||||||
|
|
||||||
gl_FragColor = sum / 12.0;
|
|
||||||
}
|
|
||||||
)#";
|
|
||||||
|
|
||||||
inline const std::string TEXFRAGSRCEXT = R"#(
|
|
||||||
#extension GL_OES_EGL_image_external : require
|
|
||||||
|
|
||||||
precision mediump float;
|
|
||||||
varying vec2 v_texcoord;
|
|
||||||
uniform samplerExternalOES texture0;
|
|
||||||
uniform float alpha;
|
|
||||||
|
|
||||||
uniform vec2 topLeft;
|
|
||||||
uniform vec2 bottomRight;
|
|
||||||
uniform vec2 fullSize;
|
|
||||||
uniform float radius;
|
|
||||||
|
|
||||||
uniform int discardOpaque;
|
|
||||||
|
|
||||||
uniform int primitiveMultisample;
|
|
||||||
uniform int ignoreCorners;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
|
|
||||||
vec4 pixColor = texture2D(texture0, v_texcoord);
|
|
||||||
|
|
||||||
if (discardOpaque == 1 && pixColor[3] * alpha == 1.0) {
|
|
||||||
discard;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
vec2 pixCoord = fullSize * v_texcoord;
|
|
||||||
|
|
||||||
)#" + ROUNDED_SHADER_FUNC("pixColor") + R"#(
|
|
||||||
|
|
||||||
gl_FragColor = pixColor * alpha;
|
|
||||||
})#";
|
|
66
src/render/decorations/CHyprDropShadowDecoration.cpp
Normal file
66
src/render/decorations/CHyprDropShadowDecoration.cpp
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
#include "CHyprDropShadowDecoration.hpp"
|
||||||
|
|
||||||
|
#include "../../Compositor.hpp"
|
||||||
|
|
||||||
|
CHyprDropShadowDecoration::CHyprDropShadowDecoration(CWindow* pWindow) {
|
||||||
|
m_pWindow = pWindow;
|
||||||
|
}
|
||||||
|
|
||||||
|
CHyprDropShadowDecoration::~CHyprDropShadowDecoration() {
|
||||||
|
updateWindow(m_pWindow);
|
||||||
|
}
|
||||||
|
|
||||||
|
SWindowDecorationExtents CHyprDropShadowDecoration::getWindowDecorationExtents() {
|
||||||
|
static auto *const PSHADOWS = &g_pConfigManager->getConfigValuePtr("decoration:drop_shadow")->intValue;
|
||||||
|
|
||||||
|
if (*PSHADOWS != 1)
|
||||||
|
return {{}, {}};
|
||||||
|
|
||||||
|
return m_seExtents;
|
||||||
|
}
|
||||||
|
|
||||||
|
eDecorationType CHyprDropShadowDecoration::getDecorationType() {
|
||||||
|
return DECORATION_SHADOW;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CHyprDropShadowDecoration::damageEntire() {
|
||||||
|
static auto *const PSHADOWS = &g_pConfigManager->getConfigValuePtr("decoration:drop_shadow")->intValue;
|
||||||
|
|
||||||
|
if (*PSHADOWS != 1)
|
||||||
|
return; // disabled
|
||||||
|
|
||||||
|
wlr_box dm = {m_vLastWindowPos.x - m_seExtents.topLeft.x, m_vLastWindowPos.y - m_seExtents.topLeft.y, m_vLastWindowSize.x + m_seExtents.topLeft.x + m_seExtents.bottomRight.x, m_vLastWindowSize.y + m_seExtents.topLeft.y + m_seExtents.bottomRight.y};
|
||||||
|
g_pHyprRenderer->damageBox(&dm);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CHyprDropShadowDecoration::updateWindow(CWindow* pWindow) {
|
||||||
|
damageEntire();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CHyprDropShadowDecoration::draw(SMonitor* pMonitor, float a) {
|
||||||
|
|
||||||
|
if (!g_pCompositor->windowValidMapped(m_pWindow))
|
||||||
|
return;
|
||||||
|
|
||||||
|
static auto *const PSHADOWS = &g_pConfigManager->getConfigValuePtr("decoration:drop_shadow")->intValue;
|
||||||
|
static auto *const PSHADOWSIZE = &g_pConfigManager->getConfigValuePtr("decoration:shadow_range")->intValue;
|
||||||
|
static auto *const PROUNDING = &g_pConfigManager->getConfigValuePtr("decoration:rounding")->intValue;
|
||||||
|
|
||||||
|
if (*PSHADOWS != 1)
|
||||||
|
return; // disabled
|
||||||
|
|
||||||
|
// update the extents if needed
|
||||||
|
if (*PSHADOWSIZE != m_seExtents.topLeft.x)
|
||||||
|
m_seExtents = {{*PSHADOWSIZE + 2, *PSHADOWSIZE + 2}, {*PSHADOWSIZE + 2, *PSHADOWSIZE + 2}};
|
||||||
|
|
||||||
|
m_vLastWindowPos = m_pWindow->m_vRealPosition.vec();
|
||||||
|
m_vLastWindowSize = m_pWindow->m_vRealSize.vec();
|
||||||
|
|
||||||
|
// draw the shadow
|
||||||
|
wlr_box fullBox = {m_vLastWindowPos.x - m_seExtents.topLeft.x + 2, m_vLastWindowPos.y - m_seExtents.topLeft.y + 2, m_vLastWindowSize.x + m_seExtents.topLeft.x + m_seExtents.bottomRight.x - 4, m_vLastWindowSize.y + m_seExtents.topLeft.y + m_seExtents.bottomRight.y - 4};
|
||||||
|
|
||||||
|
fullBox.x -= pMonitor->vecPosition.x;
|
||||||
|
fullBox.y -= pMonitor->vecPosition.y;
|
||||||
|
|
||||||
|
g_pHyprOpenGL->renderRoundedShadow(&fullBox, *PROUNDING, *PSHADOWSIZE, a);
|
||||||
|
}
|
27
src/render/decorations/CHyprDropShadowDecoration.hpp
Normal file
27
src/render/decorations/CHyprDropShadowDecoration.hpp
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "IHyprWindowDecoration.hpp"
|
||||||
|
|
||||||
|
class CHyprDropShadowDecoration : public IHyprWindowDecoration {
|
||||||
|
public:
|
||||||
|
CHyprDropShadowDecoration(CWindow*);
|
||||||
|
virtual ~CHyprDropShadowDecoration();
|
||||||
|
|
||||||
|
virtual SWindowDecorationExtents getWindowDecorationExtents();
|
||||||
|
|
||||||
|
virtual void draw(SMonitor*, float a);
|
||||||
|
|
||||||
|
virtual eDecorationType getDecorationType();
|
||||||
|
|
||||||
|
virtual void updateWindow(CWindow*);
|
||||||
|
|
||||||
|
virtual void damageEntire();
|
||||||
|
|
||||||
|
private:
|
||||||
|
SWindowDecorationExtents m_seExtents;
|
||||||
|
|
||||||
|
CWindow* m_pWindow = nullptr;
|
||||||
|
|
||||||
|
Vector2D m_vLastWindowPos;
|
||||||
|
Vector2D m_vLastWindowSize;
|
||||||
|
};
|
@@ -68,7 +68,7 @@ void CHyprGroupBarDecoration::damageEntire() {
|
|||||||
g_pHyprRenderer->damageBox(&dm);
|
g_pHyprRenderer->damageBox(&dm);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CHyprGroupBarDecoration::draw(SMonitor* pMonitor) {
|
void CHyprGroupBarDecoration::draw(SMonitor* pMonitor, float a) {
|
||||||
// get how many bars we will draw
|
// get how many bars we will draw
|
||||||
int barsToDraw = m_dwGroupMembers.size();
|
int barsToDraw = m_dwGroupMembers.size();
|
||||||
|
|
||||||
@@ -88,6 +88,7 @@ void CHyprGroupBarDecoration::draw(SMonitor* pMonitor) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
CColor color = m_dwGroupMembers[i] == g_pCompositor->m_pLastWindow ? CColor(g_pConfigManager->getInt("dwindle:col.group_border_active")) : CColor(g_pConfigManager->getInt("dwindle:col.group_border"));
|
CColor color = m_dwGroupMembers[i] == g_pCompositor->m_pLastWindow ? CColor(g_pConfigManager->getInt("dwindle:col.group_border_active")) : CColor(g_pConfigManager->getInt("dwindle:col.group_border"));
|
||||||
|
color.a *= a;
|
||||||
g_pHyprOpenGL->renderRect(&rect, color);
|
g_pHyprOpenGL->renderRect(&rect, color);
|
||||||
|
|
||||||
xoff += PAD + BARW;
|
xoff += PAD + BARW;
|
||||||
|
@@ -10,7 +10,7 @@ public:
|
|||||||
|
|
||||||
virtual SWindowDecorationExtents getWindowDecorationExtents();
|
virtual SWindowDecorationExtents getWindowDecorationExtents();
|
||||||
|
|
||||||
virtual void draw(SMonitor*);
|
virtual void draw(SMonitor*, float a);
|
||||||
|
|
||||||
virtual eDecorationType getDecorationType();
|
virtual eDecorationType getDecorationType();
|
||||||
|
|
||||||
|
@@ -4,7 +4,8 @@
|
|||||||
|
|
||||||
enum eDecorationType {
|
enum eDecorationType {
|
||||||
DECORATION_NONE = -1,
|
DECORATION_NONE = -1,
|
||||||
DECORATION_GROUPBAR
|
DECORATION_GROUPBAR,
|
||||||
|
DECORATION_SHADOW
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SWindowDecorationExtents {
|
struct SWindowDecorationExtents {
|
||||||
@@ -21,7 +22,7 @@ public:
|
|||||||
|
|
||||||
virtual SWindowDecorationExtents getWindowDecorationExtents() = 0;
|
virtual SWindowDecorationExtents getWindowDecorationExtents() = 0;
|
||||||
|
|
||||||
virtual void draw(SMonitor*) = 0;
|
virtual void draw(SMonitor*, float a) = 0;
|
||||||
|
|
||||||
virtual eDecorationType getDecorationType() = 0;
|
virtual eDecorationType getDecorationType() = 0;
|
||||||
|
|
||||||
|
91
src/render/shaders/Border.hpp
Normal file
91
src/render/shaders/Border.hpp
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
// makes a stencil without corners
|
||||||
|
inline const std::string FRAGBORDER1 = R"#(
|
||||||
|
precision mediump float;
|
||||||
|
varying vec4 v_color;
|
||||||
|
varying vec2 v_texcoord;
|
||||||
|
|
||||||
|
uniform vec2 topLeft;
|
||||||
|
uniform vec2 bottomRight;
|
||||||
|
uniform vec2 fullSize;
|
||||||
|
uniform float radius;
|
||||||
|
uniform float thick;
|
||||||
|
uniform int primitiveMultisample;
|
||||||
|
|
||||||
|
float getOpacityForPixAndCorner(vec2 pix, vec2 corner) {
|
||||||
|
|
||||||
|
if (primitiveMultisample == 0) {
|
||||||
|
float dis = distance(pix + vec2(0.5, 0.5), corner);
|
||||||
|
return dis < radius && dis > radius - thick ? 1.0 : 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
float distance1 = distance(pix + vec2(0.25, 0.25), corner);
|
||||||
|
float distance2 = distance(pix + vec2(0.75, 0.25), corner);
|
||||||
|
float distance3 = distance(pix + vec2(0.25, 0.75), corner);
|
||||||
|
float distance4 = distance(pix + vec2(0.75, 0.75), corner);
|
||||||
|
|
||||||
|
float v1 = distance1 < radius && distance1 > radius - thick ? 1.0 : 0.0;
|
||||||
|
float v2 = distance2 < radius && distance2 > radius - thick ? 1.0 : 0.0;
|
||||||
|
float v3 = distance3 < radius && distance3 > radius - thick ? 1.0 : 0.0;
|
||||||
|
float v4 = distance4 < radius && distance4 > radius - thick ? 1.0 : 0.0;
|
||||||
|
|
||||||
|
return (v1 + v2 + v3 + v4) / 4.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
|
||||||
|
vec2 pixCoord = fullSize * v_texcoord;
|
||||||
|
|
||||||
|
vec4 pixColor = v_color;
|
||||||
|
|
||||||
|
bool done = false;
|
||||||
|
|
||||||
|
// check for edges
|
||||||
|
if (pixCoord[0] < topLeft[0]) {
|
||||||
|
if (pixCoord[1] < topLeft[1]) {
|
||||||
|
// top left
|
||||||
|
pixColor[3] = pixColor[3] * getOpacityForPixAndCorner(pixCoord, topLeft + vec2(1,1));
|
||||||
|
done = true;
|
||||||
|
} else if (pixCoord[1] > bottomRight[1]) {
|
||||||
|
// bottom left
|
||||||
|
pixColor[3] = pixColor[3] * getOpacityForPixAndCorner(pixCoord, vec2(topLeft[0] + 1.0, bottomRight[1]));
|
||||||
|
done = true;
|
||||||
|
}
|
||||||
|
} else if (pixCoord[0] > bottomRight[0]) {
|
||||||
|
if (pixCoord[1] < topLeft[1]) {
|
||||||
|
// top right
|
||||||
|
pixColor[3] = pixColor[3] * getOpacityForPixAndCorner(pixCoord, vec2(bottomRight[0], topLeft[1] + 1.0));
|
||||||
|
done = true;
|
||||||
|
} else if (pixCoord[1] > bottomRight[1]) {
|
||||||
|
// bottom right
|
||||||
|
pixColor[3] = pixColor[3] * getOpacityForPixAndCorner(pixCoord, bottomRight);
|
||||||
|
done = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// now check for other shit
|
||||||
|
if (!done) {
|
||||||
|
// distance to all straight bb borders
|
||||||
|
float distanceT = pixCoord[1];
|
||||||
|
float distanceB = fullSize[1] - pixCoord[1];
|
||||||
|
float distanceL = pixCoord[0];
|
||||||
|
float distanceR = fullSize[0] - pixCoord[0];
|
||||||
|
|
||||||
|
// get the smallest
|
||||||
|
float smallest = min(min(distanceT, distanceB), min(distanceL, distanceR));
|
||||||
|
|
||||||
|
if (smallest > thick) {
|
||||||
|
discard; return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pixColor[3] == 0.0) {
|
||||||
|
discard; return;
|
||||||
|
}
|
||||||
|
|
||||||
|
gl_FragColor = pixColor;
|
||||||
|
}
|
||||||
|
)#";
|
83
src/render/shaders/Shadow.hpp
Normal file
83
src/render/shaders/Shadow.hpp
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
inline const std::string FRAGSHADOW = R"#(
|
||||||
|
precision mediump float;
|
||||||
|
varying vec4 v_color;
|
||||||
|
varying vec2 v_texcoord;
|
||||||
|
|
||||||
|
uniform vec2 topLeft;
|
||||||
|
uniform vec2 bottomRight;
|
||||||
|
uniform vec2 fullSize;
|
||||||
|
uniform float radius;
|
||||||
|
uniform float range;
|
||||||
|
uniform float shadowPower;
|
||||||
|
uniform int ignoreWindow;
|
||||||
|
|
||||||
|
float pixAlphaRoundedDistance(float distanceToCorner) {
|
||||||
|
if (distanceToCorner > radius) {
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (distanceToCorner > radius - range) {
|
||||||
|
return pow((range - (distanceToCorner - radius + range)) / range, shadowPower); // i think?
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
|
||||||
|
vec4 pixColor = v_color;
|
||||||
|
float originalAlpha = pixColor[3];
|
||||||
|
|
||||||
|
bool done = false;
|
||||||
|
|
||||||
|
vec2 pixCoord = fullSize * v_texcoord;
|
||||||
|
|
||||||
|
// ok, now we check the distance to a border.
|
||||||
|
|
||||||
|
if (pixCoord[0] < topLeft[0]) {
|
||||||
|
if (pixCoord[1] < topLeft[1]) {
|
||||||
|
// top left
|
||||||
|
pixColor[3] = pixColor[3] * pixAlphaRoundedDistance(distance(pixCoord, topLeft));
|
||||||
|
done = true;
|
||||||
|
} else if (pixCoord[1] > bottomRight[1]) {
|
||||||
|
// bottom left
|
||||||
|
pixColor[3] = pixColor[3] * pixAlphaRoundedDistance(distance(pixCoord, vec2(topLeft[0], bottomRight[1])));
|
||||||
|
done = true;
|
||||||
|
}
|
||||||
|
} else if (pixCoord[0] > bottomRight[0]) {
|
||||||
|
if (pixCoord[1] < topLeft[1]) {
|
||||||
|
// top right
|
||||||
|
pixColor[3] = pixColor[3] * pixAlphaRoundedDistance(distance(pixCoord, vec2(bottomRight[0], topLeft[1])));
|
||||||
|
done = true;
|
||||||
|
} else if (pixCoord[1] > bottomRight[1]) {
|
||||||
|
// bottom right
|
||||||
|
pixColor[3] = pixColor[3] * pixAlphaRoundedDistance(distance(pixCoord, bottomRight));
|
||||||
|
done = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!done) {
|
||||||
|
// distance to all straight bb borders
|
||||||
|
float distanceT = pixCoord[1];
|
||||||
|
float distanceB = fullSize[1] - pixCoord[1];
|
||||||
|
float distanceL = pixCoord[0];
|
||||||
|
float distanceR = fullSize[0] - pixCoord[0];
|
||||||
|
|
||||||
|
// get the smallest
|
||||||
|
float smallest = min(min(distanceT, distanceB), min(distanceL, distanceR));
|
||||||
|
|
||||||
|
if (smallest < range) {
|
||||||
|
pixColor[3] = pixColor[3] * pow((smallest / range), shadowPower);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pixColor[3] == 0.0 || (ignoreWindow == 1 && pixColor[3] == originalAlpha)) {
|
||||||
|
discard; return;
|
||||||
|
}
|
||||||
|
|
||||||
|
gl_FragColor = pixColor;
|
||||||
|
})#";
|
341
src/render/shaders/Textures.hpp
Normal file
341
src/render/shaders/Textures.hpp
Normal file
@@ -0,0 +1,341 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
inline static constexpr auto ROUNDED_SHADER_FUNC = [](const std::string colorVarName) -> std::string {
|
||||||
|
return R"#(
|
||||||
|
if (pixCoord[0] < topLeft[0]) {
|
||||||
|
// we're close left
|
||||||
|
if (pixCoord[1] < topLeft[1]) {
|
||||||
|
// top
|
||||||
|
|
||||||
|
if (ignoreCorners == 1) {
|
||||||
|
discard;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
float topLeftDistance = distance(topLeft, pixCoord);
|
||||||
|
|
||||||
|
if (topLeftDistance > radius - 1.0) {
|
||||||
|
if (primitiveMultisample == 0 && topLeftDistance > radius) {
|
||||||
|
discard;
|
||||||
|
return;
|
||||||
|
} else if (primitiveMultisample == 1) {
|
||||||
|
float distances = 0.0;
|
||||||
|
if (distance(topLeft, pixCoord + vec2(0.25, 0.25)) < radius) { distances = distances + 1.0; }
|
||||||
|
if (distance(topLeft, pixCoord + vec2(0.75, 0.25)) < radius) { distances = distances + 1.0; }
|
||||||
|
if (distance(topLeft, pixCoord + vec2(0.25, 0.75)) < radius) { distances = distances + 1.0; }
|
||||||
|
if (distance(topLeft, pixCoord + vec2(0.75, 0.75)) < radius) { distances = distances + 1.0; }
|
||||||
|
|
||||||
|
if (distances == 0.0) {
|
||||||
|
discard;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
distances = distances / 4.0;
|
||||||
|
|
||||||
|
gl_FragColor = )#" + colorVarName + R"#( * distances;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (pixCoord[1] > bottomRight[1]) {
|
||||||
|
// bottom
|
||||||
|
|
||||||
|
if (ignoreCorners == 1) {
|
||||||
|
discard;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
float topLeftDistance = distance(vec2(topLeft[0], bottomRight[1]), pixCoord);
|
||||||
|
|
||||||
|
if (topLeftDistance > radius - 1.0) {
|
||||||
|
if (primitiveMultisample == 0 && topLeftDistance > radius) {
|
||||||
|
discard;
|
||||||
|
return;
|
||||||
|
} else if (primitiveMultisample == 1) {
|
||||||
|
float distances = 0.0;
|
||||||
|
if (distance(vec2(topLeft[0], bottomRight[1]), pixCoord + vec2(0.25, 0.25)) < radius) { distances = distances + 1.0; }
|
||||||
|
if (distance(vec2(topLeft[0], bottomRight[1]), pixCoord + vec2(0.75, 0.25)) < radius) { distances = distances + 1.0; }
|
||||||
|
if (distance(vec2(topLeft[0], bottomRight[1]), pixCoord + vec2(0.25, 0.75)) < radius) { distances = distances + 1.0; }
|
||||||
|
if (distance(vec2(topLeft[0], bottomRight[1]), pixCoord + vec2(0.75, 0.75)) < radius) { distances = distances + 1.0; }
|
||||||
|
|
||||||
|
if (distances == 0.0) {
|
||||||
|
discard;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
distances = distances / 4.0;
|
||||||
|
|
||||||
|
gl_FragColor = )#" + colorVarName + R"#( * distances;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (pixCoord[0] > bottomRight[0]) {
|
||||||
|
// we're close right
|
||||||
|
if (pixCoord[1] < topLeft[1]) {
|
||||||
|
// top
|
||||||
|
|
||||||
|
if (ignoreCorners == 1) {
|
||||||
|
discard;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
float topLeftDistance = distance(vec2(bottomRight[0], topLeft[1]), pixCoord);
|
||||||
|
|
||||||
|
if (topLeftDistance > radius - 1.0) {
|
||||||
|
if (primitiveMultisample == 0 && topLeftDistance > radius) {
|
||||||
|
discard;
|
||||||
|
return;
|
||||||
|
} else if (primitiveMultisample == 1) {
|
||||||
|
float distances = 0.0;
|
||||||
|
if (distance(vec2(bottomRight[0], topLeft[1]), pixCoord + vec2(0.25, 0.25)) < radius) { distances = distances + 1.0; }
|
||||||
|
if (distance(vec2(bottomRight[0], topLeft[1]), pixCoord + vec2(0.75, 0.25)) < radius) { distances = distances + 1.0; }
|
||||||
|
if (distance(vec2(bottomRight[0], topLeft[1]), pixCoord + vec2(0.25, 0.75)) < radius) { distances = distances + 1.0; }
|
||||||
|
if (distance(vec2(bottomRight[0], topLeft[1]), pixCoord + vec2(0.75, 0.75)) < radius) { distances = distances + 1.0; }
|
||||||
|
|
||||||
|
if (distances == 0.0) {
|
||||||
|
discard;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
distances = distances / 4.0;
|
||||||
|
|
||||||
|
gl_FragColor = )#" + colorVarName + R"#( * distances;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (pixCoord[1] > bottomRight[1]) {
|
||||||
|
// bottom
|
||||||
|
|
||||||
|
if (ignoreCorners == 1) {
|
||||||
|
discard;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
float topLeftDistance = distance(bottomRight, pixCoord);
|
||||||
|
|
||||||
|
if (topLeftDistance > radius - 1.0) {
|
||||||
|
if (primitiveMultisample == 0 && topLeftDistance > radius) {
|
||||||
|
discard;
|
||||||
|
return;
|
||||||
|
} else if (primitiveMultisample == 1) {
|
||||||
|
float distances = 0.0;
|
||||||
|
if (distance(bottomRight, pixCoord + vec2(0.25, 0.25)) < radius) { distances = distances + 1.0; }
|
||||||
|
if (distance(bottomRight, pixCoord + vec2(0.75, 0.25)) < radius) { distances = distances + 1.0; }
|
||||||
|
if (distance(bottomRight, pixCoord + vec2(0.25, 0.75)) < radius) { distances = distances + 1.0; }
|
||||||
|
if (distance(bottomRight, pixCoord + vec2(0.75, 0.75)) < radius) { distances = distances + 1.0; }
|
||||||
|
|
||||||
|
if (distances == 0.0) {
|
||||||
|
discard;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
distances = distances / 4.0;
|
||||||
|
|
||||||
|
gl_FragColor = )#" + colorVarName + R"#( * distances;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)#";
|
||||||
|
};
|
||||||
|
|
||||||
|
inline const std::string QUADVERTSRC = R"#(
|
||||||
|
uniform mat3 proj;
|
||||||
|
uniform vec4 color;
|
||||||
|
attribute vec2 pos;
|
||||||
|
attribute vec2 texcoord;
|
||||||
|
varying vec4 v_color;
|
||||||
|
varying vec2 v_texcoord;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
gl_Position = vec4(proj * vec3(pos, 1.0), 1.0);
|
||||||
|
v_color = color;
|
||||||
|
v_texcoord = texcoord;
|
||||||
|
})#";
|
||||||
|
|
||||||
|
inline const std::string QUADFRAGSRC = R"#(
|
||||||
|
precision mediump float;
|
||||||
|
varying vec4 v_color;
|
||||||
|
varying vec2 v_texcoord;
|
||||||
|
|
||||||
|
uniform vec2 topLeft;
|
||||||
|
uniform vec2 bottomRight;
|
||||||
|
uniform vec2 fullSize;
|
||||||
|
uniform float radius;
|
||||||
|
|
||||||
|
uniform int primitiveMultisample;
|
||||||
|
uniform int ignoreCorners;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
if (radius == 0.0) {
|
||||||
|
gl_FragColor = v_color;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec2 pixCoord = fullSize * v_texcoord;
|
||||||
|
|
||||||
|
)#" + ROUNDED_SHADER_FUNC("v_color") + R"#(
|
||||||
|
|
||||||
|
gl_FragColor = v_color;
|
||||||
|
})#";
|
||||||
|
|
||||||
|
inline const std::string TEXVERTSRC = R"#(
|
||||||
|
uniform mat3 proj;
|
||||||
|
attribute vec2 pos;
|
||||||
|
attribute vec2 texcoord;
|
||||||
|
varying vec2 v_texcoord;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
gl_Position = vec4(proj * vec3(pos, 1.0), 1.0);
|
||||||
|
v_texcoord = texcoord;
|
||||||
|
})#";
|
||||||
|
|
||||||
|
inline const std::string TEXFRAGSRCRGBA = R"#(
|
||||||
|
precision mediump float;
|
||||||
|
varying vec2 v_texcoord; // is in 0-1
|
||||||
|
uniform sampler2D tex;
|
||||||
|
uniform float alpha;
|
||||||
|
|
||||||
|
uniform vec2 topLeft;
|
||||||
|
uniform vec2 bottomRight;
|
||||||
|
uniform vec2 fullSize;
|
||||||
|
uniform float radius;
|
||||||
|
|
||||||
|
uniform int discardOpaque;
|
||||||
|
|
||||||
|
uniform int primitiveMultisample;
|
||||||
|
uniform int ignoreCorners;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
|
||||||
|
vec4 pixColor = texture2D(tex, v_texcoord);
|
||||||
|
|
||||||
|
if (discardOpaque == 1 && pixColor[3] * alpha == 1.0) {
|
||||||
|
discard;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec2 pixCoord = fullSize * v_texcoord;
|
||||||
|
|
||||||
|
)#" + ROUNDED_SHADER_FUNC("pixColor") +
|
||||||
|
R"#(
|
||||||
|
|
||||||
|
gl_FragColor = pixColor * alpha;
|
||||||
|
})#";
|
||||||
|
|
||||||
|
inline const std::string TEXFRAGSRCRGBX = R"#(
|
||||||
|
precision mediump float;
|
||||||
|
varying vec2 v_texcoord;
|
||||||
|
uniform sampler2D tex;
|
||||||
|
uniform float alpha;
|
||||||
|
|
||||||
|
uniform vec2 topLeft;
|
||||||
|
uniform vec2 bottomRight;
|
||||||
|
uniform vec2 fullSize;
|
||||||
|
uniform float radius;
|
||||||
|
|
||||||
|
uniform int discardOpaque;
|
||||||
|
|
||||||
|
uniform int primitiveMultisample;
|
||||||
|
uniform int ignoreCorners;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
|
||||||
|
if (discardOpaque == 1 && alpha == 1.0) {
|
||||||
|
discard;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 pixColor = vec4(texture2D(tex, v_texcoord).rgb, 1.0);
|
||||||
|
|
||||||
|
vec2 pixCoord = fullSize * v_texcoord;
|
||||||
|
|
||||||
|
)#" + ROUNDED_SHADER_FUNC("pixColor") + R"#(
|
||||||
|
|
||||||
|
gl_FragColor = pixColor * alpha;
|
||||||
|
})#";
|
||||||
|
|
||||||
|
inline const std::string FRAGBLUR1 = R"#(
|
||||||
|
#version 100
|
||||||
|
precision mediump float;
|
||||||
|
varying mediump vec2 v_texcoord; // is in 0-1
|
||||||
|
uniform sampler2D tex;
|
||||||
|
|
||||||
|
uniform float radius;
|
||||||
|
uniform vec2 halfpixel;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
vec2 uv = v_texcoord * 2.0;
|
||||||
|
|
||||||
|
vec4 sum = texture2D(tex, uv) * 4.0;
|
||||||
|
sum += texture2D(tex, uv - halfpixel.xy * radius);
|
||||||
|
sum += texture2D(tex, uv + halfpixel.xy * radius);
|
||||||
|
sum += texture2D(tex, uv + vec2(halfpixel.x, -halfpixel.y) * radius);
|
||||||
|
sum += texture2D(tex, uv - vec2(halfpixel.x, -halfpixel.y) * radius);
|
||||||
|
gl_FragColor = sum / 8.0;
|
||||||
|
}
|
||||||
|
)#";
|
||||||
|
|
||||||
|
inline const std::string FRAGBLUR2 = R"#(
|
||||||
|
#version 100
|
||||||
|
precision mediump float;
|
||||||
|
varying mediump vec2 v_texcoord; // is in 0-1
|
||||||
|
uniform sampler2D tex;
|
||||||
|
|
||||||
|
uniform float radius;
|
||||||
|
uniform vec2 halfpixel;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
vec2 uv = v_texcoord / 2.0;
|
||||||
|
|
||||||
|
vec4 sum = texture2D(tex, uv + vec2(-halfpixel.x * 2.0, 0.0) * radius);
|
||||||
|
|
||||||
|
sum += texture2D(tex, uv + vec2(-halfpixel.x, halfpixel.y) * radius) * 2.0;
|
||||||
|
sum += texture2D(tex, uv + vec2(0.0, halfpixel.y * 2.0) * radius);
|
||||||
|
sum += texture2D(tex, uv + vec2(halfpixel.x, halfpixel.y) * radius) * 2.0;
|
||||||
|
sum += texture2D(tex, uv + vec2(halfpixel.x * 2.0, 0.0) * radius);
|
||||||
|
sum += texture2D(tex, uv + vec2(halfpixel.x, -halfpixel.y) * radius) * 2.0;
|
||||||
|
sum += texture2D(tex, uv + vec2(0.0, -halfpixel.y * 2.0) * radius);
|
||||||
|
sum += texture2D(tex, uv + vec2(-halfpixel.x, -halfpixel.y) * radius) * 2.0;
|
||||||
|
|
||||||
|
gl_FragColor = sum / 12.0;
|
||||||
|
}
|
||||||
|
)#";
|
||||||
|
|
||||||
|
inline const std::string TEXFRAGSRCEXT = R"#(
|
||||||
|
#extension GL_OES_EGL_image_external : require
|
||||||
|
|
||||||
|
precision mediump float;
|
||||||
|
varying vec2 v_texcoord;
|
||||||
|
uniform samplerExternalOES texture0;
|
||||||
|
uniform float alpha;
|
||||||
|
|
||||||
|
uniform vec2 topLeft;
|
||||||
|
uniform vec2 bottomRight;
|
||||||
|
uniform vec2 fullSize;
|
||||||
|
uniform float radius;
|
||||||
|
|
||||||
|
uniform int discardOpaque;
|
||||||
|
|
||||||
|
uniform int primitiveMultisample;
|
||||||
|
uniform int ignoreCorners;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
|
||||||
|
vec4 pixColor = texture2D(texture0, v_texcoord);
|
||||||
|
|
||||||
|
if (discardOpaque == 1 && pixColor[3] * alpha == 1.0) {
|
||||||
|
discard;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec2 pixCoord = fullSize * v_texcoord;
|
||||||
|
|
||||||
|
)#" + ROUNDED_SHADER_FUNC("pixColor") + R"#(
|
||||||
|
|
||||||
|
gl_FragColor = pixColor * alpha;
|
||||||
|
})#";
|
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
#include "../includes.hpp"
|
#include "../includes.hpp"
|
||||||
#include "../helpers/MiscFunctions.hpp"
|
#include "../helpers/MiscFunctions.hpp"
|
||||||
#include "../../ext-workspace-unstable-v1-protocol.h"
|
#include "ext-workspace-unstable-v1-protocol.h"
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
1
subprojects/wlroots
Submodule
1
subprojects/wlroots
Submodule
Submodule subprojects/wlroots added at b89ed9015c
1
wlroots
1
wlroots
Submodule wlroots deleted from 75d31509db
Reference in New Issue
Block a user