mirror of
https://github.com/hyprwm/Hyprland.git
synced 2025-08-14 19:45:45 -07:00
Compare commits
127 Commits
0.1.0-beta
...
v0.4.0beta
Author | SHA1 | Date | |
---|---|---|---|
|
b62e530fdb | ||
|
663fba76ae | ||
|
d73e05cc68 | ||
|
066ea296ff | ||
|
72c967aa89 | ||
|
c474e8253a | ||
|
20936ad2a4 | ||
|
d743ac7bb1 | ||
|
322a495412 | ||
|
63d6c594b9 | ||
|
09e77bf844 | ||
|
3d4832990c | ||
|
84a0fa0f34 | ||
|
2cd2f8b5b5 | ||
|
172d6cd498 | ||
|
02269af777 | ||
|
e2592522d3 | ||
|
d76c982d2e | ||
|
ef855440c6 | ||
|
246aa000f5 | ||
|
1a93b2a756 | ||
|
10c2bd0686 | ||
|
f99ad521a4 | ||
|
9486a230c7 | ||
|
6f3b004199 | ||
|
19b17b590c | ||
|
f9c8a72e46 | ||
|
e11cb8b328 | ||
|
7b568d7ad8 | ||
|
a2f718059b | ||
|
feb0499597 | ||
|
601abc7e92 | ||
|
7451890fd7 | ||
|
f5cdb5b95e | ||
|
7afcf656bd | ||
|
6daa866beb | ||
|
9447fcd603 | ||
|
9acf15efd7 | ||
|
b5a100379e | ||
|
4f76d5d8d7 | ||
|
8d850b0ce1 | ||
|
0f28d2ae55 | ||
|
d2451aea4b | ||
|
680705ff91 | ||
|
300fc2ab0f | ||
|
02210d3d96 | ||
|
879345c1e9 | ||
|
1e3bea5e70 | ||
|
f64cae2b7f | ||
|
c433b14e3d | ||
|
8d1c495878 | ||
|
4264a0b08d | ||
|
40ab062a3c | ||
|
35bcea38e3 | ||
|
1ccb944509 | ||
|
c600249aee | ||
|
6d6e967a8d | ||
|
970018248f | ||
|
f6b8a96621 | ||
|
8e8d5a99c2 | ||
|
471654d791 | ||
|
679e36d82e | ||
|
0f8712ed64 | ||
|
3e28a8b690 | ||
|
8de7cc5a8d | ||
|
e73df80782 | ||
|
0d7131d30e | ||
|
d2e0b7c22a | ||
|
c1193ee483 | ||
|
042e79b888 | ||
|
0055efc4f1 | ||
|
df722cbb86 | ||
|
68f7e565e6 | ||
|
48a3b1c514 | ||
|
85128ebb7d | ||
|
ad98b96891 | ||
|
2e7586e841 | ||
|
f6ba9909d6 | ||
|
c9041bf5c9 | ||
|
b2474d406a | ||
|
eee9698ec9 | ||
|
1f4c938c67 | ||
|
c44c79abb2 | ||
|
1e096f6fcd | ||
|
b1c11f3d2e | ||
|
da63503d5f | ||
|
7167be9c48 | ||
|
e81790f357 | ||
|
edf57c50ff | ||
|
e2be91582a | ||
|
7522ade58d | ||
|
3d7abfea92 | ||
|
2de65771ea | ||
|
6b60595822 | ||
|
b76b32b458 | ||
|
f5645805d8 | ||
|
15338fcf63 | ||
|
227cbb0464 | ||
|
9842730f57 | ||
|
d0ff0c0990 | ||
|
fdb3f610e5 | ||
|
d2e1899f26 | ||
|
9d3099b21f | ||
|
4cc085ac75 | ||
|
af55d5aa96 | ||
|
632d00c51c | ||
|
f06d4fca27 | ||
|
2cd5059cf1 | ||
|
65610555c4 | ||
|
3f8845a6a7 | ||
|
894ae2d742 | ||
|
08e0567d3a | ||
|
685cf1e00d | ||
|
bdf1c16195 | ||
|
b1b24cb21a | ||
|
9ede0f1c7d | ||
|
10a9325a6a | ||
|
e4d494aed4 | ||
|
5c911df351 | ||
|
15553804d6 | ||
|
7f1f14fe85 | ||
|
7d442d4851 | ||
|
8c10857f14 | ||
|
9b6960eb55 | ||
|
4cda50399c | ||
|
daff7d8ca2 | ||
|
1bef63a1e6 |
11
.github/ISSUE_TEMPLATE/bug_report.md
vendored
11
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -3,13 +3,10 @@ name: Bug report
|
|||||||
about: Found a bug? Report it here!
|
about: Found a bug? Report it here!
|
||||||
title: ''
|
title: ''
|
||||||
labels: bug
|
labels: bug
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**Describe the bug**
|
Please consult the issue guidelines at
|
||||||
|
https://github.com/vaxerski/Hyprland/blob/main/docs/ISSUE_GUIDELINES.md
|
||||||
|
BEFORE submitting.
|
||||||
**Images/videos/anything that would help**
|
|
||||||
|
|
||||||
|
|
||||||
Please attach a log (it's in /tmp/hypr/hyprland.log) and, if crashing, a crashdump (coredumpctl, then coredumpctl info <pid>)
|
|
||||||
|
5
.github/ISSUE_TEMPLATE/feature_request.md
vendored
5
.github/ISSUE_TEMPLATE/feature_request.md
vendored
@@ -3,7 +3,10 @@ name: Feature request
|
|||||||
about: Suggest a feature/change/idea
|
about: Suggest a feature/change/idea
|
||||||
title: ''
|
title: ''
|
||||||
labels: enhancement
|
labels: enhancement
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**Describe in detail your idea.**
|
Please consult the issue guidelines at
|
||||||
|
https://github.com/vaxerski/Hyprland/blob/main/docs/ISSUE_GUIDELINES.md
|
||||||
|
BEFORE submitting.
|
||||||
|
2
.github/workflows/ci.yaml
vendored
2
.github/workflows/ci.yaml
vendored
@@ -30,6 +30,8 @@ jobs:
|
|||||||
|
|
||||||
- name: Checkout Hyprland
|
- name: Checkout Hyprland
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
submodules: recursive
|
||||||
|
|
||||||
- name: Build Hyprland With default settings
|
- name: Build Hyprland With default settings
|
||||||
run: |
|
run: |
|
||||||
|
2
.github/workflows/nix-build.yaml
vendored
2
.github/workflows/nix-build.yaml
vendored
@@ -8,6 +8,8 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- name: Clone repository
|
- name: Clone repository
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
submodules: recursive
|
||||||
- name: Install nix
|
- name: Install nix
|
||||||
uses: cachix/install-nix-action@v17
|
uses: cachix/install-nix-action@v17
|
||||||
with:
|
with:
|
||||||
|
7
.github/workflows/nix-update.yaml
vendored
7
.github/workflows/nix-update.yaml
vendored
@@ -1,9 +1,6 @@
|
|||||||
name: "Nix: update lockfile"
|
name: "Nix: update lockfile"
|
||||||
|
|
||||||
on:
|
on: [push, workflow_dispatch]
|
||||||
schedule:
|
|
||||||
- cron: '0 0 */14 * *'
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
update:
|
update:
|
||||||
@@ -19,7 +16,7 @@ jobs:
|
|||||||
auto-optimise-store = true
|
auto-optimise-store = true
|
||||||
experimental-features = nix-command flakes
|
experimental-features = nix-command flakes
|
||||||
- name: Update lockfile
|
- name: Update lockfile
|
||||||
run: nix flake update
|
run: nix/update-inputs.sh
|
||||||
- uses: stefanzweifel/git-auto-commit-action@v4
|
- uses: stefanzweifel/git-auto-commit-action@v4
|
||||||
with:
|
with:
|
||||||
commit_message: "[gha] bump flake inputs"
|
commit_message: "[gha] bump flake inputs"
|
||||||
|
4
.gitignore
vendored
4
.gitignore
vendored
@@ -19,3 +19,7 @@ result
|
|||||||
.ccls-cache
|
.ccls-cache
|
||||||
|
|
||||||
hyprctl/hyprctl
|
hyprctl/hyprctl
|
||||||
|
|
||||||
|
gmon.out
|
||||||
|
*.out
|
||||||
|
*.tar.gz
|
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
[submodule "wlroots"]
|
||||||
|
path = wlroots
|
||||||
|
url = https://gitlab.freedesktop.org/wlroots/wlroots
|
15
Makefile
15
Makefile
@@ -89,6 +89,7 @@ clear:
|
|||||||
rm -rf build
|
rm -rf build
|
||||||
rm -f *.o *-protocol.h *-protocol.c
|
rm -f *.o *-protocol.h *-protocol.c
|
||||||
rm -f ./hyprctl/hyprctl
|
rm -f ./hyprctl/hyprctl
|
||||||
|
rm -rf ./wlroots/build
|
||||||
|
|
||||||
all:
|
all:
|
||||||
make config
|
make config
|
||||||
@@ -113,4 +114,16 @@ uninstall:
|
|||||||
rm -f ${PREFIX}/bin/hyprctl
|
rm -f ${PREFIX}/bin/hyprctl
|
||||||
rm -rf ${PREFIX}/share/hyprland
|
rm -rf ${PREFIX}/share/hyprland
|
||||||
|
|
||||||
config: 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
|
||||||
|
|
||||||
|
config:
|
||||||
|
make protocols
|
||||||
|
|
||||||
|
sed -i -E 's/(soversion = 11)([^032]|$$)/soversion = 11032/g' ./wlroots/meson.build
|
||||||
|
|
||||||
|
rm -rf ./wlroots/build
|
||||||
|
|
||||||
|
cd wlroots && meson ./build --prefix=/usr --buildtype=release
|
||||||
|
cd wlroots && ninja -C build/
|
||||||
|
|
||||||
|
cd wlroots && sudo ninja -C build/ install
|
||||||
|
18
README.md
18
README.md
@@ -37,10 +37,9 @@ For Hyprland without the `land` part, see [Hypr], the Xorg window manager.
|
|||||||
|
|
||||||
# Notice
|
# Notice
|
||||||
|
|
||||||
This project is still in its early development, expect bugs.
|
Hyprland is still in pretty early development compared to some other Wayland compositors.
|
||||||
|
|
||||||
Once you get it working though, it's pretty stable.<br/>
|
|
||||||
|
|
||||||
|
Although Hyprland is pretty stable, it may have some bugs.
|
||||||
|
|
||||||
### Help Wanted
|
### Help Wanted
|
||||||
|
|
||||||
@@ -51,17 +50,20 @@ 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
|
||||||
- Bezier-curve window animations
|
|
||||||
- Custom bezier curve based animations
|
- Custom bezier curve based animations
|
||||||
- Workspaces protocol support
|
- wlr_ext workspaces protocol support
|
||||||
- Dual Kawase blur
|
- Dual Kawase blur
|
||||||
- Window fade in / out
|
- Fully dynamic workspaces
|
||||||
|
- Closely follows wlroots-git
|
||||||
|
- Bundled wlroots
|
||||||
|
- Window / layer fade in / out
|
||||||
- Tiling / floating / fullscreen windows
|
- Tiling / floating / fullscreen windows
|
||||||
|
- Special Workspace (Scratchpad)
|
||||||
- Window / monitor rules
|
- Window / monitor rules
|
||||||
- Socket-based IPC
|
- Socket-based IPC
|
||||||
|
- Event System for bash scripts
|
||||||
- Rounded corners
|
- Rounded corners
|
||||||
- Damage tracking ( *Experimental* )
|
- Full Damage tracking
|
||||||
- Moving / resizing
|
|
||||||
- Docks support
|
- Docks support
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
|
71
aur/PKGBUILD
Normal file
71
aur/PKGBUILD
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
# 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}"
|
||||||
|
}
|
55
aur/PKGBUILD-bin
Normal file
55
aur/PKGBUILD-bin
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
# 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,16 +1,54 @@
|
|||||||
# Maintainer: Sander van Kasteel <info@sandervankasteel.nl>, ThatOneCalculator <kainoa@t1c.dev>
|
# Maintainer: ThatOneCalculator <kainoa@t1c.dev>, Sander van Kasteel <info@sandervankasteel.nl>
|
||||||
|
|
||||||
_pkgname="hyprland"
|
_pkgname="hyprland"
|
||||||
pkgname="${_pkgname}-git"
|
pkgname="${_pkgname}-git"
|
||||||
pkgver=r461.96cdf8f
|
pkgver=r655.gef85544
|
||||||
pkgrel=5
|
pkgrel=1
|
||||||
pkgdesc="Hyprland is a dynamic tiling Wayland compositor based on wlroots that doesn't sacrifice on its looks."
|
pkgdesc="Hyprland is a dynamic tiling Wayland compositor based on wlroots that doesn't sacrifice on its looks."
|
||||||
arch=(any)
|
arch=(any)
|
||||||
url="https://github.com/vaxerski/Hyprland"
|
url="https://github.com/vaxerski/Hyprland"
|
||||||
license=('BSD')
|
license=('BSD')
|
||||||
depends=(libxcb xcb-proto xcb-util xcb-util-keysyms libxfixes libx11 libxcomposite xorg-xinput libxrender pixman wayland-protocols wlroots-git cairo pango)
|
depends=(
|
||||||
makedepends=(git cmake ninja gcc gdb)
|
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")
|
source=("${_pkgname}::git+https://github.com/vaxerski/Hyprland.git")
|
||||||
|
conflicts=("${_pkgname}-git" "${_pkgname}" "${_pkgname}-bin")
|
||||||
sha256sums=('SKIP')
|
sha256sums=('SKIP')
|
||||||
options=(!makeflags !buildflags)
|
options=(!makeflags !buildflags)
|
||||||
|
|
||||||
@@ -24,6 +62,7 @@ pkgver() {
|
|||||||
|
|
||||||
build() {
|
build() {
|
||||||
cd "${srcdir}/${_pkgname}"
|
cd "${srcdir}/${_pkgname}"
|
||||||
|
git submodule update --init
|
||||||
make all
|
make all
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,32 +0,0 @@
|
|||||||
|
|
||||||
# Contributing
|
|
||||||
|
|
||||||
*Thank you for considering contributing to Hyprland.*
|
|
||||||
|
|
||||||
## Development
|
|
||||||
|
|
||||||
Check the [Wiki] for debugging instructions.
|
|
||||||
|
|
||||||
Afterwards, pick yourself an [Issue] or implement your own suggestion.
|
|
||||||
|
|
||||||
An good place to search for things to contribute is the [Projects Page]
|
|
||||||
|
|
||||||
*As Hyprland is still in its early stages of development, I'd recommend you stick to bug fixes first.*
|
|
||||||
|
|
||||||
## Pull Requests
|
|
||||||
|
|
||||||
- Please follow the code style
|
|
||||||
|
|
||||||
- Code must be readable
|
|
||||||
|
|
||||||
- Features should be useful
|
|
||||||
|
|
||||||
- Test your changes!
|
|
||||||
|
|
||||||
*Run it on bare metal and check if everything works.*
|
|
||||||
|
|
||||||
<!----------------------------------------------------------------------------->
|
|
||||||
|
|
||||||
[Issue]: https://github.com/vaxerski/Hyprland/issues
|
|
||||||
[Wiki]: https://github.com/vaxerski/Hyprland/wiki/Contributing-&-Debugging
|
|
||||||
[Projects page]: https://github.com/vaxerski/Hyprland/projects?type=beta
|
|
56
docs/ISSUE_GUIDELINES.md
Normal file
56
docs/ISSUE_GUIDELINES.md
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
# Issue Guidelines
|
||||||
|
|
||||||
|
First of all, please remember to:
|
||||||
|
- Check that your issue is not a duplicate
|
||||||
|
- Read the [FAQ](https://github.com/vaxerski/Hyprland/wiki/FAQ)
|
||||||
|
- Read the [Configuring Page](https://github.com/vaxerski/Hyprland/wiki/Configuring-Hyprland)
|
||||||
|
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
# Reporting suggestions
|
||||||
|
Suggestions are welcome.
|
||||||
|
|
||||||
|
Many features can be implemented using bash scripts and Hyprland sockets, read up on those [Here](https://github.com/vaxerski/Hyprland/wiki/IPC). Please do not suggest features that can be implemented as such.
|
||||||
|
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
# Reporting bugs
|
||||||
|
|
||||||
|
All bug reports should have the following:
|
||||||
|
- Steps to reproduce
|
||||||
|
- Expected outcome
|
||||||
|
- Noted outcome
|
||||||
|
|
||||||
|
If your bug is one that doesn't crash Hyprland, but feels like invalid behavior, that's all you need to say.
|
||||||
|
|
||||||
|
If your bug crashes Hyprland, append additionally:
|
||||||
|
- The Hyprland log
|
||||||
|
- Coredump / Coredump analysis (with a stacktrace)
|
||||||
|
|
||||||
|
## 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
|
||||||
|
```
|
||||||
|
cat /tmp/hypr/$(ls -t /tmp/hypr/ | head -n 1)/hyprland.log
|
||||||
|
```
|
||||||
|
feel free to send it to a file, save, copy, etc.
|
||||||
|
|
||||||
|
if you are in a Hyprland session, and you want the log of the last session, use
|
||||||
|
```
|
||||||
|
cat /tmp/hypr/$(ls -t /tmp/hypr/ | head -n 2 | tail -n 1)/hyprland.log
|
||||||
|
```
|
||||||
|
|
||||||
|
basically, directories in /tmp/hypr are your sessions.
|
||||||
|
|
||||||
|
## Obtaining the Hyprland coredump
|
||||||
|
If you are on systemd, you can simply use
|
||||||
|
```
|
||||||
|
coredumpctl
|
||||||
|
```
|
||||||
|
then go to the end (press END on your keyboard) and remember the PID of the last `Hyprland` occurrence. It's the first number after the time, for example `2891`.
|
||||||
|
|
||||||
|
exit coredumpctl (ctrl+c) and use
|
||||||
|
```
|
||||||
|
coredumpctl info [PID]
|
||||||
|
```
|
||||||
|
where `[PID]` is the PID you remembered.
|
||||||
|
|
@@ -1,35 +0,0 @@
|
|||||||
|
|
||||||
# Installation
|
|
||||||
|
|
||||||
## Packages
|
|
||||||
|
|
||||||
*I do not maintain any packages, but some kind people have made them for me.*
|
|
||||||
|
|
||||||
**If I missed any, please let me know.**
|
|
||||||
|
|
||||||
## Notice
|
|
||||||
|
|
||||||
Since I am not the maintainer, I cannot guarantee that those packages will always work and be up to date.
|
|
||||||
|
|
||||||
***Use at your own disclosure.*** <br>
|
|
||||||
*If they don't work, try building manually.*
|
|
||||||
|
|
||||||
#### Arch ( AUR / -git )
|
|
||||||
|
|
||||||
```sh
|
|
||||||
yay -S hyprland-git
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
|
|
||||||
## Building / No XWayland / other
|
|
||||||
|
|
||||||
If your distro doesn't have **Hyprland** in its repositories, you want to modify it, or use custom build flags, please refer to the **[Wiki Page][Install]** for the installation instructions.
|
|
||||||
|
|
||||||
|
|
||||||
<!----------------------------------------------------------------------------->
|
|
||||||
|
|
||||||
[Install]: https://github.com/vaxerski/Hyprland/wiki/Installation
|
|
||||||
|
|
||||||
|
|
@@ -27,7 +27,7 @@ general {
|
|||||||
col.active_border=0x66ee1111
|
col.active_border=0x66ee1111
|
||||||
col.inactive_border=0x66333333
|
col.inactive_border=0x66333333
|
||||||
|
|
||||||
damage_tracking=full # experimental, monitor is 100% fine, but full might have some minor bugs, especially with high blur settings!
|
damage_tracking=full # leave it on full unless you hate your GPU and want to make it suffer
|
||||||
}
|
}
|
||||||
|
|
||||||
decoration {
|
decoration {
|
||||||
@@ -64,7 +64,7 @@ dwindle {
|
|||||||
# example binds
|
# example binds
|
||||||
bind=SUPER,Q,exec,kitty
|
bind=SUPER,Q,exec,kitty
|
||||||
bind=SUPER,C,killactive,
|
bind=SUPER,C,killactive,
|
||||||
bind=SUPER,M,exec,pkill Hyprland
|
bind=SUPER,M,exit,
|
||||||
bind=SUPER,E,exec,dolphin
|
bind=SUPER,E,exec,dolphin
|
||||||
bind=SUPER,V,togglefloating,
|
bind=SUPER,V,togglefloating,
|
||||||
bind=SUPER,R,exec,wofi --show drun -o DP-3
|
bind=SUPER,R,exec,wofi --show drun -o DP-3
|
||||||
|
12
flake.lock
generated
12
flake.lock
generated
@@ -2,11 +2,11 @@
|
|||||||
"nodes": {
|
"nodes": {
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1653407748,
|
"lastModified": 1653931853,
|
||||||
"narHash": "sha256-g9puJaILRTb9ttlLQ7IehpV7Wcy0n+vs8LOFu6ylQcM=",
|
"narHash": "sha256-O3wncIouj9x7gBPntzHeK/Hkmm9M1SGlYq7JI7saTAE=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "5ce6597eca7d7b518c03ecda57d45f9404b5e060",
|
"rev": "f1c167688a6f81f4a51ab542e5f476c8c595e457",
|
||||||
"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": 1653502661,
|
"lastModified": 1653658290,
|
||||||
"narHash": "sha256-unQ1j3jleghIMi340dJTJZZ1ffwm1cI7gaQbdKd7laE=",
|
"narHash": "sha256-zZaona39DOZNL93A1KG3zAi8vDttJBirxacq24hWCn4=",
|
||||||
"owner": "wlroots",
|
"owner": "wlroots",
|
||||||
"repo": "wlroots",
|
"repo": "wlroots",
|
||||||
"rev": "1cb6b2cf673a5b580d7ad79ce2b37c14b14b0268",
|
"rev": "75d31509db8c28e8379fe9570118ef8c82284581",
|
||||||
"type": "gitlab"
|
"type": "gitlab"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
@@ -33,18 +33,18 @@
|
|||||||
in {
|
in {
|
||||||
packages = genSystems (system: {
|
packages = genSystems (system: {
|
||||||
wlroots = pkgsFor.${system}.wlroots.overrideAttrs (prev: {
|
wlroots = pkgsFor.${system}.wlroots.overrideAttrs (prev: {
|
||||||
version = mkVersion inputs.wlroots.lastModifiedDate;
|
version = mkVersion (toString (inputs.wlroots.lastModifiedDate or inputs.wlroots.lastModified or "19700101"));
|
||||||
src = inputs.wlroots;
|
src = inputs.wlroots;
|
||||||
});
|
});
|
||||||
default = pkgsFor.${system}.callPackage ./default.nix {
|
default = pkgsFor.${system}.callPackage ./nix/default.nix {
|
||||||
version = mkVersion self.lastModifiedDate;
|
version = mkVersion (toString (self.lastModifiedDate or self.lastModified or "19700101"));
|
||||||
inherit (self.packages.${system}) wlroots;
|
inherit (self.packages.${system}) wlroots;
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
formatter = genSystems (system: pkgsFor.${system}.alejandra);
|
formatter = genSystems (system: pkgsFor.${system}.alejandra);
|
||||||
|
|
||||||
nixosModules.default = import ./module.nix self;
|
nixosModules.default = import ./nix/module.nix self;
|
||||||
|
|
||||||
# Deprecated
|
# Deprecated
|
||||||
overlays.default = _: prev: {
|
overlays.default = _: prev: {
|
||||||
|
@@ -23,6 +23,7 @@ usage: hyprctl [command] [(opt)args]
|
|||||||
clients
|
clients
|
||||||
activewindow
|
activewindow
|
||||||
layers
|
layers
|
||||||
|
devices
|
||||||
dispatch
|
dispatch
|
||||||
keyword
|
keyword
|
||||||
version
|
version
|
||||||
@@ -44,12 +45,25 @@ void request(std::string arg) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// get the instance signature
|
||||||
|
auto instanceSig = getenv("HYPRLAND_INSTANCE_SIGNATURE");
|
||||||
|
|
||||||
|
if (!instanceSig) {
|
||||||
|
std::cout << "HYPRLAND_INSTANCE_SIGNATURE was not set! (Is Hyprland running?)";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string instanceSigStr = std::string(instanceSig);
|
||||||
|
|
||||||
sockaddr_un serverAddress = {0};
|
sockaddr_un serverAddress = {0};
|
||||||
serverAddress.sun_family = AF_UNIX;
|
serverAddress.sun_family = AF_UNIX;
|
||||||
strcpy(serverAddress.sun_path, "/tmp/hypr/.socket.sock");
|
|
||||||
|
std::string socketPath = "/tmp/hypr/" + instanceSigStr + "/.socket.sock";
|
||||||
|
|
||||||
|
strcpy(serverAddress.sun_path, socketPath.c_str());
|
||||||
|
|
||||||
if (connect(SERVERSOCKET, (sockaddr*)&serverAddress, SUN_LEN(&serverAddress)) < 0) {
|
if (connect(SERVERSOCKET, (sockaddr*)&serverAddress, SUN_LEN(&serverAddress)) < 0) {
|
||||||
std::cout << "Couldn't connect to /tmp/hypr/.socket.sock. (3) Is Hyprland running?";
|
std::cout << "Couldn't connect to " << socketPath << ". (3)";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -117,6 +131,7 @@ int main(int argc, char** argv) {
|
|||||||
else if (!strcmp(argv[1], "activewindow")) request("activewindow");
|
else if (!strcmp(argv[1], "activewindow")) request("activewindow");
|
||||||
else if (!strcmp(argv[1], "layers")) request("layers");
|
else if (!strcmp(argv[1], "layers")) request("layers");
|
||||||
else if (!strcmp(argv[1], "version")) request("version");
|
else if (!strcmp(argv[1], "version")) request("version");
|
||||||
|
else if (!strcmp(argv[1], "devices")) request("devices");
|
||||||
else if (!strcmp(argv[1], "reload")) request("reload");
|
else if (!strcmp(argv[1], "reload")) request("reload");
|
||||||
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);
|
||||||
|
@@ -24,7 +24,7 @@
|
|||||||
stdenv.mkDerivation {
|
stdenv.mkDerivation {
|
||||||
pname = "hyprland";
|
pname = "hyprland";
|
||||||
inherit version;
|
inherit version;
|
||||||
src = ./.;
|
src = ../.;
|
||||||
|
|
||||||
nativeBuildInputs = [
|
nativeBuildInputs = [
|
||||||
cmake
|
cmake
|
||||||
@@ -52,8 +52,12 @@ stdenv.mkDerivation {
|
|||||||
["-DCMAKE_BUILD_TYPE=Release"]
|
["-DCMAKE_BUILD_TYPE=Release"]
|
||||||
++ lib.optional (!enableXWayland) "-DNO_XWAYLAND=true";
|
++ lib.optional (!enableXWayland) "-DNO_XWAYLAND=true";
|
||||||
|
|
||||||
|
# enables building with nix-supplied wlroots instead of submodule
|
||||||
prePatch = ''
|
prePatch = ''
|
||||||
make config
|
sed -Ei 's/"\.\.\/wlroots\/include\/([a-zA-Z0-9./_-]+)"/<\1>/g' src/includes.hpp
|
||||||
|
'';
|
||||||
|
postPatch = ''
|
||||||
|
make protocols
|
||||||
'';
|
'';
|
||||||
|
|
||||||
postBuild = ''
|
postBuild = ''
|
19
nix/update-inputs.sh
Executable file
19
nix/update-inputs.sh
Executable file
@@ -0,0 +1,19 @@
|
|||||||
|
#!/usr/bin/env -S nix shell nixpkgs#gawk nixpkgs#git nixpkgs#moreutils nixpkgs#jq -c bash
|
||||||
|
|
||||||
|
# get wlroots revision from submodule
|
||||||
|
SUB_REV=$(git submodule status | awk '{ print substr($1,2)}')
|
||||||
|
# and from lockfile
|
||||||
|
CRT_REV=$(jq < flake.lock '.nodes.wlroots.locked.rev' -r)
|
||||||
|
|
||||||
|
if [ $SUB_REV != $CRT_REV ]; then
|
||||||
|
# update nixpkgs to latest version
|
||||||
|
nix flake lock --update-input nixpkgs
|
||||||
|
|
||||||
|
# update wlroots to submodule revision
|
||||||
|
nix flake lock --override-input wlroots "gitlab:wlroots/wlroots/$SUB_REV?host=gitlab.freedesktop.org"
|
||||||
|
|
||||||
|
# remove "dirty" mark from lockfile
|
||||||
|
jq < flake.lock 'del(.nodes.wlroots.original.rev)' | sponge flake.lock
|
||||||
|
else
|
||||||
|
echo "wlroots is up to date!"
|
||||||
|
fi
|
@@ -1,11 +1,16 @@
|
|||||||
#include "Compositor.hpp"
|
#include "Compositor.hpp"
|
||||||
|
|
||||||
CCompositor::CCompositor() {
|
CCompositor::CCompositor() {
|
||||||
unlink("/tmp/hypr/hyprland.log");
|
m_szInstanceSignature = GIT_COMMIT_HASH + std::string("_") + std::to_string(time(NULL));
|
||||||
unlink("/tmp/hypr/hyprlandd.log");
|
|
||||||
unlink("/tmp/hypr/.hyprlandrq");
|
|
||||||
|
|
||||||
system("mkdir -p /tmp/hypr");
|
Debug::init(m_szInstanceSignature);
|
||||||
|
|
||||||
|
Debug::log(LOG, "Instance Signature: %s", m_szInstanceSignature.c_str());
|
||||||
|
|
||||||
|
setenv("HYPRLAND_INSTANCE_SIGNATURE", m_szInstanceSignature.c_str(), true);
|
||||||
|
|
||||||
|
const auto INSTANCEPATH = "/tmp/hypr/" + m_szInstanceSignature;
|
||||||
|
mkdir(INSTANCEPATH.c_str(), S_IRWXU | S_IRWXG);
|
||||||
|
|
||||||
m_sWLDisplay = wl_display_create();
|
m_sWLDisplay = wl_display_create();
|
||||||
|
|
||||||
@@ -67,7 +72,7 @@ CCompositor::CCompositor() {
|
|||||||
m_sWLRScene = wlr_scene_create();
|
m_sWLRScene = wlr_scene_create();
|
||||||
wlr_scene_attach_output_layout(m_sWLRScene, m_sWLROutputLayout);
|
wlr_scene_attach_output_layout(m_sWLRScene, m_sWLROutputLayout);
|
||||||
|
|
||||||
m_sWLRXDGShell = wlr_xdg_shell_create(m_sWLDisplay, 2);
|
m_sWLRXDGShell = wlr_xdg_shell_create(m_sWLDisplay, 3);
|
||||||
|
|
||||||
m_sWLRCursor = wlr_cursor_create();
|
m_sWLRCursor = wlr_cursor_create();
|
||||||
wlr_cursor_attach_output_layout(m_sWLRCursor, m_sWLROutputLayout);
|
wlr_cursor_attach_output_layout(m_sWLRCursor, m_sWLROutputLayout);
|
||||||
@@ -102,6 +107,8 @@ CCompositor::CCompositor() {
|
|||||||
m_sWLRVKeyboardMgr = wlr_virtual_keyboard_manager_v1_create(m_sWLDisplay);
|
m_sWLRVKeyboardMgr = wlr_virtual_keyboard_manager_v1_create(m_sWLDisplay);
|
||||||
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
CCompositor::~CCompositor() {
|
CCompositor::~CCompositor() {
|
||||||
@@ -135,6 +142,7 @@ void CCompositor::initAllSignals() {
|
|||||||
addWLSignal(&m_sWLRPointerConstraints->events.new_constraint, &Events::listen_newConstraint, m_sWLRPointerConstraints, "PointerConstraints");
|
addWLSignal(&m_sWLRPointerConstraints->events.new_constraint, &Events::listen_newConstraint, m_sWLRPointerConstraints, "PointerConstraints");
|
||||||
addWLSignal(&m_sWLRXDGDecoMgr->events.new_toplevel_decoration, &Events::listen_NewXDGDeco, m_sWLRXDGDecoMgr, "XDGDecoMgr");
|
addWLSignal(&m_sWLRXDGDecoMgr->events.new_toplevel_decoration, &Events::listen_NewXDGDeco, m_sWLRXDGDecoMgr, "XDGDecoMgr");
|
||||||
addWLSignal(&m_sWLRVirtPtrMgr->events.new_virtual_pointer, &Events::listen_newVirtPtr, m_sWLRVirtPtrMgr, "VirtPtrMgr");
|
addWLSignal(&m_sWLRVirtPtrMgr->events.new_virtual_pointer, &Events::listen_newVirtPtr, m_sWLRVirtPtrMgr, "VirtPtrMgr");
|
||||||
|
addWLSignal(&m_sWLRRenderer->events.destroy, &Events::listen_RendererDestroy, m_sWLRRenderer, "WLRRenderer");
|
||||||
|
|
||||||
signal(SIGINT, handleCritSignal);
|
signal(SIGINT, handleCritSignal);
|
||||||
signal(SIGTERM, handleCritSignal);
|
signal(SIGTERM, handleCritSignal);
|
||||||
@@ -144,6 +152,12 @@ void CCompositor::cleanupExit() {
|
|||||||
if (!m_sWLDisplay)
|
if (!m_sWLDisplay)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
m_pLastFocus = nullptr;
|
||||||
|
m_pLastWindow = nullptr;
|
||||||
|
|
||||||
|
m_lWorkspaces.clear();
|
||||||
|
m_lWindows.clear();
|
||||||
|
|
||||||
if (g_pXWaylandManager->m_sWLRXWayland) {
|
if (g_pXWaylandManager->m_sWLRXWayland) {
|
||||||
wlr_xwayland_destroy(g_pXWaylandManager->m_sWLRXWayland);
|
wlr_xwayland_destroy(g_pXWaylandManager->m_sWLRXWayland);
|
||||||
g_pXWaylandManager->m_sWLRXWayland = nullptr;
|
g_pXWaylandManager->m_sWLRXWayland = nullptr;
|
||||||
@@ -192,6 +206,9 @@ void CCompositor::startCompositor() {
|
|||||||
Debug::log(LOG, "Creating the EventManager!");
|
Debug::log(LOG, "Creating the EventManager!");
|
||||||
g_pEventManager = std::make_unique<CEventManager>();
|
g_pEventManager = std::make_unique<CEventManager>();
|
||||||
g_pEventManager->startThread();
|
g_pEventManager->startThread();
|
||||||
|
|
||||||
|
Debug::log(LOG, "Creating the HyprDebugOverlay!");
|
||||||
|
g_pDebugOverlay = std::make_unique<CHyprDebugOverlay>();
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
|
|
||||||
@@ -244,6 +261,16 @@ SMonitor* CCompositor::getMonitorFromID(const int& id) {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SMonitor* CCompositor::getMonitorFromName(const std::string& name) {
|
||||||
|
for (auto& m : m_lMonitors) {
|
||||||
|
if (m.szName == name) {
|
||||||
|
return &m;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
SMonitor* CCompositor::getMonitorFromCursor() {
|
SMonitor* CCompositor::getMonitorFromCursor() {
|
||||||
const auto COORDS = Vector2D(m_sWLRCursor->x, m_sWLRCursor->y);
|
const auto COORDS = Vector2D(m_sWLRCursor->x, m_sWLRCursor->y);
|
||||||
|
|
||||||
@@ -293,6 +320,15 @@ bool CCompositor::windowExists(CWindow* pWindow) {
|
|||||||
|
|
||||||
CWindow* CCompositor::vectorToWindow(const Vector2D& pos) {
|
CWindow* CCompositor::vectorToWindow(const Vector2D& pos) {
|
||||||
const auto PMONITOR = getMonitorFromVector(pos);
|
const auto PMONITOR = getMonitorFromVector(pos);
|
||||||
|
|
||||||
|
if (PMONITOR->specialWorkspaceOpen) {
|
||||||
|
for (auto& w : m_lWindows) {
|
||||||
|
wlr_box box = {w.m_vRealPosition.vec().x, w.m_vRealPosition.vec().y, w.m_vRealSize.vec().x, w.m_vRealSize.vec().y};
|
||||||
|
if (w.m_iWorkspaceID == SPECIAL_WORKSPACE_ID && wlr_box_contains_point(&box, pos.x, pos.y) && w.m_bIsMapped && !w.m_bIsFloating && !w.m_bHidden)
|
||||||
|
return &w;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// first loop over floating cuz they're above, m_lWindows should be sorted bottom->top, for tiled it doesn't matter.
|
// first loop over floating cuz they're above, m_lWindows should be sorted bottom->top, for tiled it doesn't matter.
|
||||||
for (auto w = m_lWindows.rbegin(); w != m_lWindows.rend(); w++) {
|
for (auto w = m_lWindows.rbegin(); w != m_lWindows.rend(); w++) {
|
||||||
wlr_box box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y};
|
wlr_box box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y};
|
||||||
@@ -311,6 +347,15 @@ CWindow* CCompositor::vectorToWindow(const Vector2D& pos) {
|
|||||||
|
|
||||||
CWindow* CCompositor::vectorToWindowTiled(const Vector2D& pos) {
|
CWindow* CCompositor::vectorToWindowTiled(const Vector2D& pos) {
|
||||||
const auto PMONITOR = getMonitorFromVector(pos);
|
const auto PMONITOR = getMonitorFromVector(pos);
|
||||||
|
|
||||||
|
if (PMONITOR->specialWorkspaceOpen) {
|
||||||
|
for (auto& w : m_lWindows) {
|
||||||
|
wlr_box box = {w.m_vPosition.x, w.m_vPosition.y, w.m_vSize.x, w.m_vSize.y};
|
||||||
|
if (w.m_iWorkspaceID == SPECIAL_WORKSPACE_ID && wlr_box_contains_point(&box, pos.x, pos.y) && !w.m_bIsFloating && !w.m_bHidden)
|
||||||
|
return &w;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (auto& w : m_lWindows) {
|
for (auto& w : m_lWindows) {
|
||||||
wlr_box box = {w.m_vPosition.x, w.m_vPosition.y, w.m_vSize.x, w.m_vSize.y};
|
wlr_box box = {w.m_vPosition.x, w.m_vPosition.y, w.m_vSize.x, w.m_vSize.y};
|
||||||
if (w.m_bIsMapped && wlr_box_contains_point(&box, pos.x, pos.y) && w.m_iWorkspaceID == PMONITOR->activeWorkspace && !w.m_bIsFloating && !w.m_bHidden)
|
if (w.m_bIsMapped && wlr_box_contains_point(&box, pos.x, pos.y) && w.m_iWorkspaceID == PMONITOR->activeWorkspace && !w.m_bIsFloating && !w.m_bHidden)
|
||||||
@@ -322,6 +367,16 @@ CWindow* CCompositor::vectorToWindowTiled(const Vector2D& pos) {
|
|||||||
|
|
||||||
CWindow* CCompositor::vectorToWindowIdeal(const Vector2D& pos) {
|
CWindow* CCompositor::vectorToWindowIdeal(const Vector2D& pos) {
|
||||||
const auto PMONITOR = getMonitorFromVector(pos);
|
const auto PMONITOR = getMonitorFromVector(pos);
|
||||||
|
|
||||||
|
// special workspace
|
||||||
|
if (PMONITOR->specialWorkspaceOpen) {
|
||||||
|
for (auto& w : m_lWindows) {
|
||||||
|
wlr_box box = {w.m_vPosition.x, w.m_vPosition.y, w.m_vSize.x, w.m_vSize.y};
|
||||||
|
if (w.m_iWorkspaceID == SPECIAL_WORKSPACE_ID && w.m_bIsMapped && wlr_box_contains_point(&box, pos.x, pos.y) && !w.m_bHidden)
|
||||||
|
return &w;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// first loop over floating cuz they're above, m_lWindows should be sorted bottom->top, for tiled it doesn't matter.
|
// first loop over floating cuz they're above, m_lWindows should be sorted bottom->top, for tiled it doesn't matter.
|
||||||
for (auto w = m_lWindows.rbegin(); w != m_lWindows.rend(); w++) {
|
for (auto w = m_lWindows.rbegin(); w != m_lWindows.rend(); w++) {
|
||||||
wlr_box box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y};
|
wlr_box box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y};
|
||||||
@@ -341,6 +396,14 @@ CWindow* CCompositor::vectorToWindowIdeal(const Vector2D& pos) {
|
|||||||
CWindow* CCompositor::windowFromCursor() {
|
CWindow* CCompositor::windowFromCursor() {
|
||||||
const auto PMONITOR = getMonitorFromCursor();
|
const auto PMONITOR = getMonitorFromCursor();
|
||||||
|
|
||||||
|
if (PMONITOR->specialWorkspaceOpen) {
|
||||||
|
for (auto& w : m_lWindows) {
|
||||||
|
wlr_box box = {w.m_vPosition.x, w.m_vPosition.y, w.m_vSize.x, w.m_vSize.y};
|
||||||
|
if (w.m_iWorkspaceID == SPECIAL_WORKSPACE_ID && wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y) && w.m_bIsMapped)
|
||||||
|
return &w;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// first loop over floating cuz they're above, m_lWindows should be sorted bottom->top, for tiled it doesn't matter.
|
// first loop over floating cuz they're above, m_lWindows should be sorted bottom->top, for tiled it doesn't matter.
|
||||||
for (auto w = m_lWindows.rbegin(); w != m_lWindows.rend(); w++) {
|
for (auto w = m_lWindows.rbegin(); w != m_lWindows.rend(); w++) {
|
||||||
wlr_box box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y};
|
wlr_box box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y};
|
||||||
@@ -433,6 +496,9 @@ void CCompositor::focusWindow(CWindow* pWindow, wlr_surface* pSurface) {
|
|||||||
wlr_seat_keyboard_notify_clear_focus(m_sSeat.seat);
|
wlr_seat_keyboard_notify_clear_focus(m_sSeat.seat);
|
||||||
wlr_seat_pointer_clear_focus(m_sSeat.seat);
|
wlr_seat_pointer_clear_focus(m_sSeat.seat);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (PLASTWINDOW->m_phForeignToplevel)
|
||||||
|
wlr_foreign_toplevel_handle_v1_set_activated(PLASTWINDOW->m_phForeignToplevel, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_pLastWindow = PLASTWINDOW;
|
m_pLastWindow = PLASTWINDOW;
|
||||||
@@ -451,6 +517,9 @@ void CCompositor::focusWindow(CWindow* pWindow, wlr_surface* pSurface) {
|
|||||||
|
|
||||||
// Send an event
|
// Send an event
|
||||||
g_pEventManager->postEvent(SHyprIPCEvent("activewindow", g_pXWaylandManager->getAppIDClass(pWindow) + "," + pWindow->m_szTitle));
|
g_pEventManager->postEvent(SHyprIPCEvent("activewindow", g_pXWaylandManager->getAppIDClass(pWindow) + "," + pWindow->m_szTitle));
|
||||||
|
|
||||||
|
if (pWindow->m_phForeignToplevel)
|
||||||
|
wlr_foreign_toplevel_handle_v1_set_activated(pWindow->m_phForeignToplevel, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CCompositor::focusSurface(wlr_surface* pSurface, CWindow* pWindowOwner) {
|
void CCompositor::focusSurface(wlr_surface* pSurface, CWindow* pWindowOwner) {
|
||||||
@@ -549,6 +618,9 @@ bool CCompositor::isWorkspaceVisible(const int& w) {
|
|||||||
for (auto& m : m_lMonitors) {
|
for (auto& m : m_lMonitors) {
|
||||||
if (m.activeWorkspace == w)
|
if (m.activeWorkspace == w)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
if (m.specialWorkspaceOpen && w == SPECIAL_WORKSPACE_ID)
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@@ -565,7 +637,15 @@ CWorkspace* CCompositor::getWorkspaceByID(const int& id) {
|
|||||||
|
|
||||||
void CCompositor::sanityCheckWorkspaces() {
|
void CCompositor::sanityCheckWorkspaces() {
|
||||||
for (auto it = m_lWorkspaces.begin(); it != m_lWorkspaces.end(); ++it) {
|
for (auto it = m_lWorkspaces.begin(); it != m_lWorkspaces.end(); ++it) {
|
||||||
if (getWindowsOnWorkspace(it->m_iID) == 0 && !isWorkspaceVisible(it->m_iID)) {
|
if ((getWindowsOnWorkspace(it->m_iID) == 0 && !isWorkspaceVisible(it->m_iID))) {
|
||||||
|
it = m_lWorkspaces.erase(it);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (it->m_iID == SPECIAL_WORKSPACE_ID && getWindowsOnWorkspace(it->m_iID) == 0) {
|
||||||
|
for (auto& m : m_lMonitors) {
|
||||||
|
m.specialWorkspaceOpen = false;
|
||||||
|
}
|
||||||
|
|
||||||
it = m_lWorkspaces.erase(it);
|
it = m_lWorkspaces.erase(it);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -595,6 +675,9 @@ void CCompositor::fixXWaylandWindowsOnWorkspace(const int& id) {
|
|||||||
|
|
||||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(id);
|
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(id);
|
||||||
|
|
||||||
|
if (!PWORKSPACE)
|
||||||
|
return;
|
||||||
|
|
||||||
for (auto& w : m_lWindows) {
|
for (auto& w : m_lWindows) {
|
||||||
if (w.m_iWorkspaceID == id) {
|
if (w.m_iWorkspaceID == id) {
|
||||||
|
|
||||||
@@ -614,6 +697,9 @@ bool CCompositor::doesSeatAcceptInput(wlr_surface* surface) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool CCompositor::isWindowActive(CWindow* pWindow) {
|
bool CCompositor::isWindowActive(CWindow* pWindow) {
|
||||||
|
if (!m_pLastWindow && !m_pLastFocus)
|
||||||
|
return false;
|
||||||
|
|
||||||
if (!windowValidMapped(pWindow))
|
if (!windowValidMapped(pWindow))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@@ -790,8 +876,8 @@ CWorkspace* CCompositor::getWorkspaceByString(const std::string& str) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
int id = std::stoi(str);
|
std::string name = "";
|
||||||
return getWorkspaceByID(id);
|
return getWorkspaceByID(getWorkspaceIDFromString(str, name));
|
||||||
} catch (std::exception& e) {
|
} catch (std::exception& e) {
|
||||||
Debug::log(ERR, "Error in getWorkspaceByString, invalid id");
|
Debug::log(ERR, "Error in getWorkspaceByString, invalid id");
|
||||||
}
|
}
|
||||||
@@ -906,4 +992,102 @@ void CCompositor::updateWindowBorderColor(CWindow* pWindow) {
|
|||||||
pWindow->m_cRealBorderColor = RENDERDATA.borderColor;
|
pWindow->m_cRealBorderColor = RENDERDATA.borderColor;
|
||||||
else
|
else
|
||||||
pWindow->m_cRealBorderColor = CColor(pWindow == m_pLastWindow ? *ACTIVECOL : *INACTIVECOL);
|
pWindow->m_cRealBorderColor = CColor(pWindow == m_pLastWindow ? *ACTIVECOL : *INACTIVECOL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCompositor::moveWindowToWorkspace(CWindow* pWindow, const std::string& work) {
|
||||||
|
m_pLastWindow = pWindow;
|
||||||
|
g_pKeybindManager->moveActiveToWorkspace(work);
|
||||||
|
|
||||||
|
g_pInputManager->refocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
int CCompositor::getNextAvailableMonitorID() {
|
||||||
|
int64_t topID = -1;
|
||||||
|
for (auto& m : m_lMonitors) {
|
||||||
|
if ((int64_t)m.ID > topID)
|
||||||
|
topID = m.ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
return topID + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCompositor::moveWorkspaceToMonitor(CWorkspace* pWorkspace, SMonitor* pMonitor) {
|
||||||
|
|
||||||
|
// We trust the workspace and monitor to be correct.
|
||||||
|
|
||||||
|
if (pWorkspace->m_iMonitorID == pMonitor->ID)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Debug::log(LOG, "moveWorkspaceToMonitor: Moving %d to monitor %d", pWorkspace->m_iID, pMonitor->ID);
|
||||||
|
|
||||||
|
const auto POLDMON = getMonitorFromID(pWorkspace->m_iMonitorID);
|
||||||
|
|
||||||
|
const bool SWITCHINGISACTIVE = POLDMON->activeWorkspace == pWorkspace->m_iID;
|
||||||
|
|
||||||
|
// fix old mon
|
||||||
|
int nextWorkspaceOnMonitorID = -1;
|
||||||
|
for (auto& w : m_lWorkspaces) {
|
||||||
|
if (w.m_iMonitorID == POLDMON->ID && w.m_iID != pWorkspace->m_iID) {
|
||||||
|
nextWorkspaceOnMonitorID = w.m_iID;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nextWorkspaceOnMonitorID == -1) {
|
||||||
|
nextWorkspaceOnMonitorID = 1;
|
||||||
|
|
||||||
|
while (getWorkspaceByID(nextWorkspaceOnMonitorID))
|
||||||
|
nextWorkspaceOnMonitorID++;
|
||||||
|
|
||||||
|
Debug::log(LOG, "moveWorkspaceToMonitor: Plugging gap with new %d", nextWorkspaceOnMonitorID);
|
||||||
|
}
|
||||||
|
|
||||||
|
Debug::log(LOG, "moveWorkspaceToMonitor: Plugging gap with existing %d", nextWorkspaceOnMonitorID);
|
||||||
|
|
||||||
|
g_pKeybindManager->focusMonitor(std::to_string(POLDMON->ID));
|
||||||
|
g_pKeybindManager->changeworkspace(std::to_string(nextWorkspaceOnMonitorID));
|
||||||
|
|
||||||
|
// move the workspace
|
||||||
|
|
||||||
|
pWorkspace->m_iMonitorID = pMonitor->ID;
|
||||||
|
pWorkspace->moveToMonitor(pMonitor->ID);
|
||||||
|
|
||||||
|
for (auto& w : m_lWindows) {
|
||||||
|
if (w.m_iWorkspaceID == pWorkspace->m_iID)
|
||||||
|
w.m_iMonitorID = pMonitor->ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SWITCHINGISACTIVE) { // if it was active, preserve its' status. If it wasn't, don't.
|
||||||
|
Debug::log(LOG, "moveWorkspaceToMonitor: SWITCHINGISACTIVE, active %d -> %d", pMonitor->activeWorkspace, pWorkspace->m_iID);
|
||||||
|
|
||||||
|
if (const auto PWORKSPACE = getWorkspaceByID(pMonitor->activeWorkspace); PWORKSPACE)
|
||||||
|
getWorkspaceByID(pMonitor->activeWorkspace)->startAnim(false, false);
|
||||||
|
|
||||||
|
pMonitor->activeWorkspace = pWorkspace->m_iID;
|
||||||
|
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(pMonitor->ID);
|
||||||
|
|
||||||
|
pWorkspace->startAnim(true, true, true);
|
||||||
|
|
||||||
|
wlr_cursor_warp(m_sWLRCursor, m_sSeat.mouse->mouse, pMonitor->vecPosition.x + pMonitor->vecTransformedSize.x / 2, pMonitor->vecPosition.y + pMonitor->vecTransformedSize.y / 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// finalize
|
||||||
|
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(POLDMON->ID);
|
||||||
|
|
||||||
|
g_pInputManager->refocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CCompositor::workspaceIDOutOfBounds(const int& id) {
|
||||||
|
int lowestID = 99999;
|
||||||
|
int highestID = -99999;
|
||||||
|
|
||||||
|
for (auto& w : m_lWorkspaces) {
|
||||||
|
if (w.m_iID < lowestID)
|
||||||
|
lowestID = w.m_iID;
|
||||||
|
|
||||||
|
if (w.m_iID > highestID)
|
||||||
|
highestID = w.m_iID;
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::clamp(id, lowestID, highestID) != id;
|
||||||
}
|
}
|
@@ -15,6 +15,7 @@
|
|||||||
#include "managers/KeybindManager.hpp"
|
#include "managers/KeybindManager.hpp"
|
||||||
#include "managers/AnimationManager.hpp"
|
#include "managers/AnimationManager.hpp"
|
||||||
#include "managers/EventManager.hpp"
|
#include "managers/EventManager.hpp"
|
||||||
|
#include "debug/HyprDebugOverlay.hpp"
|
||||||
#include "helpers/Monitor.hpp"
|
#include "helpers/Monitor.hpp"
|
||||||
#include "helpers/Workspace.hpp"
|
#include "helpers/Workspace.hpp"
|
||||||
#include "Window.hpp"
|
#include "Window.hpp"
|
||||||
@@ -57,10 +58,12 @@ public:
|
|||||||
wlr_server_decoration_manager* m_sWLRServerDecoMgr;
|
wlr_server_decoration_manager* m_sWLRServerDecoMgr;
|
||||||
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;
|
||||||
// ------------------------------------------------- //
|
// ------------------------------------------------- //
|
||||||
|
|
||||||
|
|
||||||
const char* m_szWLDisplaySocket;
|
const char* m_szWLDisplaySocket;
|
||||||
|
std::string m_szInstanceSignature = "";
|
||||||
|
|
||||||
std::list<SMonitor> m_lMonitors;
|
std::list<SMonitor> m_lMonitors;
|
||||||
std::list<CWindow> m_lWindows;
|
std::list<CWindow> m_lWindows;
|
||||||
@@ -84,6 +87,7 @@ public:
|
|||||||
// ------------------------------------------------- //
|
// ------------------------------------------------- //
|
||||||
|
|
||||||
SMonitor* getMonitorFromID(const int&);
|
SMonitor* getMonitorFromID(const int&);
|
||||||
|
SMonitor* getMonitorFromName(const std::string&);
|
||||||
SMonitor* getMonitorFromCursor();
|
SMonitor* getMonitorFromCursor();
|
||||||
SMonitor* getMonitorFromVector(const Vector2D&);
|
SMonitor* getMonitorFromVector(const Vector2D&);
|
||||||
void removeWindowFromVectorSafe(CWindow*);
|
void removeWindowFromVectorSafe(CWindow*);
|
||||||
@@ -123,6 +127,10 @@ public:
|
|||||||
SMonitor* getMonitorInDirection(const char&);
|
SMonitor* getMonitorInDirection(const char&);
|
||||||
void updateAllWindowsBorders();
|
void updateAllWindowsBorders();
|
||||||
void updateWindowBorderColor(CWindow*);
|
void updateWindowBorderColor(CWindow*);
|
||||||
|
void moveWindowToWorkspace(CWindow*, const std::string&);
|
||||||
|
int getNextAvailableMonitorID();
|
||||||
|
void moveWorkspaceToMonitor(CWorkspace*, SMonitor*);
|
||||||
|
bool workspaceIDOutOfBounds(const int&);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void initAllSignals();
|
void initAllSignals();
|
||||||
|
@@ -13,4 +13,34 @@ CWindow::~CWindow() {
|
|||||||
g_pCompositor->m_pLastFocus = nullptr;
|
g_pCompositor->m_pLastFocus = nullptr;
|
||||||
g_pCompositor->m_pLastWindow = nullptr;
|
g_pCompositor->m_pLastWindow = nullptr;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
wlr_box CWindow::getFullWindowBoundingBox() {
|
||||||
|
|
||||||
|
SWindowDecorationExtents maxExtents;
|
||||||
|
|
||||||
|
for (auto& wd : m_dWindowDecorations) {
|
||||||
|
|
||||||
|
const auto EXTENTS = wd->getWindowDecorationExtents();
|
||||||
|
|
||||||
|
if (EXTENTS.topLeft.x > maxExtents.topLeft.x)
|
||||||
|
maxExtents.topLeft.x = EXTENTS.topLeft.x;
|
||||||
|
|
||||||
|
if (EXTENTS.topLeft.y > maxExtents.topLeft.y)
|
||||||
|
maxExtents.topLeft.y = EXTENTS.topLeft.y;
|
||||||
|
|
||||||
|
if (EXTENTS.bottomRight.x > maxExtents.bottomRight.x)
|
||||||
|
maxExtents.bottomRight.x = EXTENTS.bottomRight.x;
|
||||||
|
|
||||||
|
if (EXTENTS.bottomRight.y > maxExtents.bottomRight.y)
|
||||||
|
maxExtents.bottomRight.y = EXTENTS.bottomRight.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add extents to the real base BB and return
|
||||||
|
wlr_box finalBox = {m_vRealPosition.vec().x - maxExtents.topLeft.x,
|
||||||
|
m_vRealPosition.vec().y - maxExtents.topLeft.y,
|
||||||
|
m_vRealSize.vec().x + maxExtents.topLeft.x + maxExtents.bottomRight.x,
|
||||||
|
m_vRealSize.vec().y + maxExtents.topLeft.y + maxExtents.bottomRight.y};
|
||||||
|
|
||||||
|
return finalBox;
|
||||||
}
|
}
|
@@ -4,13 +4,17 @@
|
|||||||
#include "events/Events.hpp"
|
#include "events/Events.hpp"
|
||||||
#include "helpers/SubsurfaceTree.hpp"
|
#include "helpers/SubsurfaceTree.hpp"
|
||||||
#include "helpers/AnimatedVariable.hpp"
|
#include "helpers/AnimatedVariable.hpp"
|
||||||
|
#include "render/decorations/IHyprWindowDecoration.hpp"
|
||||||
|
#include <deque>
|
||||||
|
|
||||||
struct SWindowSpecialRenderData {
|
struct SWindowSpecialRenderData {
|
||||||
float alpha = 1.f;
|
float alpha = 1.f;
|
||||||
|
float alphaInactive = -1.f; // -1 means unset
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SWindowAdditionalConfigData {
|
struct SWindowAdditionalConfigData {
|
||||||
std::string animationStyle = "";
|
std::string animationStyle = "";
|
||||||
|
int rounding = -1; // -1 means no
|
||||||
};
|
};
|
||||||
|
|
||||||
class CWindow {
|
class CWindow {
|
||||||
@@ -81,10 +85,18 @@ public:
|
|||||||
CAnimatedVariable m_fAlpha;
|
CAnimatedVariable m_fAlpha;
|
||||||
bool m_bFadingOut = false;
|
bool m_bFadingOut = false;
|
||||||
bool m_bReadyToDelete = false;
|
bool m_bReadyToDelete = false;
|
||||||
|
Vector2D m_vOriginalClosedPos; // these will be used for calculations later on in
|
||||||
|
Vector2D m_vOriginalClosedSize; // drawing the closing animations
|
||||||
|
|
||||||
// For hidden windows and stuff
|
// For hidden windows and stuff
|
||||||
bool m_bHidden = false;
|
bool m_bHidden = false;
|
||||||
|
|
||||||
|
// Foreign Toplevel proto
|
||||||
|
wlr_foreign_toplevel_handle_v1* m_phForeignToplevel = nullptr;
|
||||||
|
|
||||||
|
// Window decorations
|
||||||
|
std::deque<std::unique_ptr<IHyprWindowDecoration>> m_dWindowDecorations;
|
||||||
|
|
||||||
// Special render data, rules, etc
|
// Special render data, rules, etc
|
||||||
SWindowSpecialRenderData m_sSpecialRenderData;
|
SWindowSpecialRenderData m_sSpecialRenderData;
|
||||||
SWindowAdditionalConfigData m_sAdditionalConfigData;
|
SWindowAdditionalConfigData m_sAdditionalConfigData;
|
||||||
@@ -94,4 +106,7 @@ public:
|
|||||||
return m_uSurface.xdg == rhs.m_uSurface.xdg && m_uSurface.xwayland == rhs.m_uSurface.xwayland && m_vPosition == rhs.m_vPosition && m_vSize == rhs.m_vSize && m_bFadingOut == rhs.m_bFadingOut;
|
return m_uSurface.xdg == rhs.m_uSurface.xdg && m_uSurface.xwayland == rhs.m_uSurface.xwayland && m_vPosition == rhs.m_vPosition && m_vSize == rhs.m_vSize && m_bFadingOut == rhs.m_bFadingOut;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// methods
|
||||||
|
wlr_box getFullWindowBoundingBox();
|
||||||
|
|
||||||
};
|
};
|
@@ -35,20 +35,24 @@ void CConfigManager::setDefaultVars() {
|
|||||||
|
|
||||||
configValues["debug:int"].intValue = 0;
|
configValues["debug:int"].intValue = 0;
|
||||||
configValues["debug:log_damage"].intValue = 0;
|
configValues["debug:log_damage"].intValue = 0;
|
||||||
|
configValues["debug:overlay"].intValue = 0;
|
||||||
|
|
||||||
configValues["decoration:rounding"].intValue = 1;
|
configValues["decoration:rounding"].intValue = 1;
|
||||||
configValues["decoration:blur"].intValue = 1;
|
configValues["decoration:blur"].intValue = 1;
|
||||||
configValues["decoration:blur_size"].intValue = 8;
|
configValues["decoration:blur_size"].intValue = 8;
|
||||||
configValues["decoration:blur_passes"].intValue = 1;
|
configValues["decoration:blur_passes"].intValue = 1;
|
||||||
|
configValues["decoration:blur_ignore_opacity"].intValue = 0;
|
||||||
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["dwindle:pseudotile"].intValue = 0;
|
configValues["dwindle:pseudotile"].intValue = 0;
|
||||||
configValues["dwindle:col.group_border"].intValue = 0x66777700;
|
configValues["dwindle:col.group_border"].intValue = 0x66777700;
|
||||||
configValues["dwindle:col.group_border_active"].intValue = 0x66ffff00;
|
configValues["dwindle:col.group_border_active"].intValue = 0x66ffff00;
|
||||||
configValues["dwindle:force_split"].intValue = 0;
|
configValues["dwindle:force_split"].intValue = 0;
|
||||||
configValues["dwindle:preserve_split"].intValue = 0;
|
configValues["dwindle:preserve_split"].intValue = 0;
|
||||||
|
configValues["dwindle:special_scale_factor"].floatValue = 0.8f;
|
||||||
|
|
||||||
configValues["animations:enabled"].intValue = 1;
|
configValues["animations:enabled"].intValue = 1;
|
||||||
configValues["animations:speed"].floatValue = 7.f;
|
configValues["animations:speed"].floatValue = 7.f;
|
||||||
@@ -78,6 +82,8 @@ void CConfigManager::setDefaultVars() {
|
|||||||
configValues["input:repeat_rate"].intValue = 25;
|
configValues["input:repeat_rate"].intValue = 25;
|
||||||
configValues["input:repeat_delay"].intValue = 600;
|
configValues["input:repeat_delay"].intValue = 600;
|
||||||
configValues["input:natural_scroll"].intValue = 0;
|
configValues["input:natural_scroll"].intValue = 0;
|
||||||
|
configValues["input:numlock_by_default"].intValue = 0;
|
||||||
|
configValues["input:force_no_accel"].intValue = 0;
|
||||||
configValues["input:touchpad:disable_while_typing"].intValue = 1;
|
configValues["input:touchpad:disable_while_typing"].intValue = 1;
|
||||||
|
|
||||||
configValues["input:follow_mouse"].intValue = 1;
|
configValues["input:follow_mouse"].intValue = 1;
|
||||||
@@ -184,10 +190,24 @@ void CConfigManager::handleMonitor(const std::string& command, const std::string
|
|||||||
|
|
||||||
nextItem();
|
nextItem();
|
||||||
|
|
||||||
if (curitem == "disable" || curitem == "disabled" || curitem == "addreserved") {
|
if (curitem == "disable" || curitem == "disabled" || curitem == "addreserved" || curitem == "transform") {
|
||||||
if (curitem == "disable" || curitem == "disabled")
|
if (curitem == "disable" || curitem == "disabled")
|
||||||
newrule.disabled = true;
|
newrule.disabled = true;
|
||||||
else if (curitem == "addreserved") {
|
else if (curitem == "transform") {
|
||||||
|
nextItem();
|
||||||
|
|
||||||
|
wl_output_transform transform = (wl_output_transform)std::stoi(curitem);
|
||||||
|
|
||||||
|
// overwrite if exists
|
||||||
|
for (auto& r : m_dMonitorRules) {
|
||||||
|
if (r.name == newrule.name) {
|
||||||
|
r.transform = transform;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
} else if (curitem == "addreserved") {
|
||||||
nextItem();
|
nextItem();
|
||||||
|
|
||||||
int top = std::stoi(curitem);
|
int top = std::stoi(curitem);
|
||||||
@@ -411,6 +431,7 @@ void CConfigManager::handleWindowRule(const std::string& command, const std::str
|
|||||||
&& RULE.find("monitor") != 0
|
&& RULE.find("monitor") != 0
|
||||||
&& RULE.find("nofocus") != 0
|
&& RULE.find("nofocus") != 0
|
||||||
&& RULE.find("animation") != 0
|
&& RULE.find("animation") != 0
|
||||||
|
&& RULE.find("rounding") != 0
|
||||||
&& RULE.find("workspace") != 0) {
|
&& RULE.find("workspace") != 0) {
|
||||||
Debug::log(ERR, "Invalid rule found: %s", RULE.c_str());
|
Debug::log(ERR, "Invalid rule found: %s", RULE.c_str());
|
||||||
parseError = "Invalid rule found: " + RULE;
|
parseError = "Invalid rule found: " + RULE;
|
||||||
|
@@ -30,6 +30,7 @@ struct SMonitorRule {
|
|||||||
float refreshRate = 60;
|
float refreshRate = 60;
|
||||||
int defaultWorkspaceID = -1;
|
int defaultWorkspaceID = -1;
|
||||||
bool disabled = false;
|
bool disabled = false;
|
||||||
|
wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SMonitorAdditionalReservedArea {
|
struct SMonitorAdditionalReservedArea {
|
||||||
|
@@ -34,7 +34,7 @@ general {
|
|||||||
col.active_border=0x66ee1111
|
col.active_border=0x66ee1111
|
||||||
col.inactive_border=0x66333333
|
col.inactive_border=0x66333333
|
||||||
|
|
||||||
damage_tracking=full # experimental, monitor is 100% fine, but full might have some minor bugs, especially with high blur settings!
|
damage_tracking=full # leave it on full unless you hate your GPU and want to make it suffer
|
||||||
}
|
}
|
||||||
|
|
||||||
decoration {
|
decoration {
|
||||||
@@ -71,7 +71,7 @@ dwindle {
|
|||||||
# example binds
|
# example binds
|
||||||
bind=SUPER,Q,exec,kitty
|
bind=SUPER,Q,exec,kitty
|
||||||
bind=SUPER,C,killactive,
|
bind=SUPER,C,killactive,
|
||||||
bind=SUPER,M,exec,pkill Hyprland
|
bind=SUPER,M,exit,
|
||||||
bind=SUPER,E,exec,dolphin
|
bind=SUPER,E,exec,dolphin
|
||||||
bind=SUPER,V,togglefloating,
|
bind=SUPER,V,togglefloating,
|
||||||
bind=SUPER,R,exec,wofi --show drun -o DP-3
|
bind=SUPER,R,exec,wofi --show drun -o DP-3
|
||||||
|
@@ -26,8 +26,9 @@ std::string monitorsRequest() {
|
|||||||
std::string clientsRequest() {
|
std::string clientsRequest() {
|
||||||
std::string result = "";
|
std::string result = "";
|
||||||
for (auto& w : g_pCompositor->m_lWindows) {
|
for (auto& w : g_pCompositor->m_lWindows) {
|
||||||
result += getFormat("Window %x -> %s:\n\tat: %i,%i\n\tsize: %i, %i\n\tworkspace: %i (%s)\n\tfloating: %i\n\n",
|
if (w.m_bIsMapped)
|
||||||
&w, w.m_szTitle.c_str(), (int)w.m_vRealPosition.vec().x, (int)w.m_vRealPosition.vec().y, (int)w.m_vRealSize.vec().x, (int)w.m_vRealSize.vec().y, w.m_iWorkspaceID, (w.m_iWorkspaceID == -1 ? "" : g_pCompositor->getWorkspaceByID(w.m_iWorkspaceID)->m_szName.c_str()), (int)w.m_bIsFloating);
|
result += getFormat("Window %x -> %s:\n\tat: %i,%i\n\tsize: %i,%i\n\tworkspace: %i (%s)\n\tfloating: %i\n\tmonitor: %i\n\tclass: %s\n\n",
|
||||||
|
&w, w.m_szTitle.c_str(), (int)w.m_vRealPosition.vec().x, (int)w.m_vRealPosition.vec().y, (int)w.m_vRealSize.vec().x, (int)w.m_vRealSize.vec().y, w.m_iWorkspaceID, (w.m_iWorkspaceID == -1 ? "" : g_pCompositor->getWorkspaceByID(w.m_iWorkspaceID) ? g_pCompositor->getWorkspaceByID(w.m_iWorkspaceID)->m_szName.c_str() : std::string("Invalid workspace " + std::to_string(w.m_iWorkspaceID)).c_str()), (int)w.m_bIsFloating, w.m_iMonitorID, g_pXWaylandManager->getAppIDClass(&w).c_str());
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -47,8 +48,8 @@ std::string activeWindowRequest() {
|
|||||||
if (!g_pCompositor->windowValidMapped(PWINDOW))
|
if (!g_pCompositor->windowValidMapped(PWINDOW))
|
||||||
return "Invalid";
|
return "Invalid";
|
||||||
|
|
||||||
return getFormat("Window %x -> %s:\n\tat: %i,%i\n\tsize: %i, %i\n\tworkspace: %i (%s)\n\tfloating: %i\n\n",
|
return getFormat("Window %x -> %s:\n\tat: %i,%i\n\tsize: %i,%i\n\tworkspace: %i (%s)\n\tfloating: %i\n\tmonitor: %i\n\tclass: %s\n\n",
|
||||||
PWINDOW, PWINDOW->m_szTitle.c_str(), (int)PWINDOW->m_vRealPosition.vec().x, (int)PWINDOW->m_vRealPosition.vec().y, (int)PWINDOW->m_vRealSize.vec().x, (int)PWINDOW->m_vRealSize.vec().y, PWINDOW->m_iWorkspaceID, (PWINDOW->m_iWorkspaceID == -1 ? "" : g_pCompositor->getWorkspaceByID(PWINDOW->m_iWorkspaceID)->m_szName.c_str()), (int)PWINDOW->m_bIsFloating);
|
PWINDOW, PWINDOW->m_szTitle.c_str(), (int)PWINDOW->m_vRealPosition.vec().x, (int)PWINDOW->m_vRealPosition.vec().y, (int)PWINDOW->m_vRealSize.vec().x, (int)PWINDOW->m_vRealSize.vec().y, PWINDOW->m_iWorkspaceID, (PWINDOW->m_iWorkspaceID == -1 ? "" : g_pCompositor->getWorkspaceByID(PWINDOW->m_iWorkspaceID)->m_szName.c_str()), (int)PWINDOW->m_bIsFloating, (int)PWINDOW->m_iMonitorID, g_pXWaylandManager->getAppIDClass(PWINDOW).c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string layersRequest() {
|
std::string layersRequest() {
|
||||||
@@ -72,6 +73,24 @@ std::string layersRequest() {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string devicesRequest() {
|
||||||
|
std::string result = "";
|
||||||
|
|
||||||
|
result += "mice:\n";
|
||||||
|
|
||||||
|
for (auto& m : g_pInputManager->m_lMice) {
|
||||||
|
result += getFormat("\tMouse at %x:\n\t\t%s\n", &m, m.mouse->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
result += "\n\nKeyboards:\n";
|
||||||
|
|
||||||
|
for (auto& k : g_pInputManager->m_lKeyboards) {
|
||||||
|
result += getFormat("\tKeyboard at %x:\n\t\t%s\n", &k, k.keyboard->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
std::string versionRequest() {
|
std::string versionRequest() {
|
||||||
std::string result = "Hyprland, built from branch " + std::string(GIT_BRANCH) + " at commit " + GIT_COMMIT_HASH + GIT_DIRTY + " (" + GIT_COMMIT_MESSAGE + ").\nflags: (if any)\n";
|
std::string result = "Hyprland, built from branch " + std::string(GIT_BRANCH) + " at commit " + GIT_COMMIT_HASH + GIT_DIRTY + " (" + GIT_COMMIT_MESSAGE + ").\nflags: (if any)\n";
|
||||||
|
|
||||||
@@ -186,6 +205,8 @@ std::string getReply(std::string request) {
|
|||||||
return versionRequest();
|
return versionRequest();
|
||||||
else if (request == "reload")
|
else if (request == "reload")
|
||||||
return reloadRequest();
|
return reloadRequest();
|
||||||
|
else if (request == "devices")
|
||||||
|
return devicesRequest();
|
||||||
else if (request.find("dispatch") == 0)
|
else if (request.find("dispatch") == 0)
|
||||||
return dispatchRequest(request);
|
return dispatchRequest(request);
|
||||||
else if (request.find("keyword") == 0)
|
else if (request.find("keyword") == 0)
|
||||||
@@ -246,11 +267,11 @@ void HyprCtl::startHyprCtlSocket() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
unlink("/tmp/hypr/.socket.sock");
|
|
||||||
|
|
||||||
sockaddr_un SERVERADDRESS = {.sun_family = AF_UNIX};
|
sockaddr_un SERVERADDRESS = {.sun_family = AF_UNIX};
|
||||||
|
|
||||||
strcpy(SERVERADDRESS.sun_path, "/tmp/hypr/.socket.sock");
|
std::string socketPath = "/tmp/hypr/" + g_pCompositor->m_szInstanceSignature + "/.socket.sock";
|
||||||
|
|
||||||
|
strcpy(SERVERADDRESS.sun_path, socketPath.c_str());
|
||||||
|
|
||||||
bind(SOCKET, (sockaddr*)&SERVERADDRESS, SUN_LEN(&SERVERADDRESS));
|
bind(SOCKET, (sockaddr*)&SERVERADDRESS, SUN_LEN(&SERVERADDRESS));
|
||||||
|
|
||||||
@@ -262,7 +283,7 @@ void HyprCtl::startHyprCtlSocket() {
|
|||||||
|
|
||||||
char readBuffer[1024] = {0};
|
char readBuffer[1024] = {0};
|
||||||
|
|
||||||
Debug::log(LOG, "Hypr socket started.");
|
Debug::log(LOG, "Hypr socket started at %s", socketPath.c_str());
|
||||||
|
|
||||||
while(1) {
|
while(1) {
|
||||||
const auto ACCEPTEDCONNECTION = accept(SOCKET, (sockaddr*)&clientAddress, &clientSize);
|
const auto ACCEPTEDCONNECTION = accept(SOCKET, (sockaddr*)&clientAddress, &clientSize);
|
||||||
|
181
src/debug/HyprDebugOverlay.cpp
Normal file
181
src/debug/HyprDebugOverlay.cpp
Normal file
@@ -0,0 +1,181 @@
|
|||||||
|
#include "HyprDebugOverlay.hpp"
|
||||||
|
#include "../Compositor.hpp"
|
||||||
|
|
||||||
|
void CHyprMonitorDebugOverlay::renderData(SMonitor* pMonitor, float µs) {
|
||||||
|
m_dLastRenderTimes.push_back(µs / 1000.f);
|
||||||
|
|
||||||
|
if (m_dLastRenderTimes.size() > (long unsigned int)pMonitor->refreshRate)
|
||||||
|
m_dLastRenderTimes.pop_front();
|
||||||
|
|
||||||
|
if (!m_pMonitor)
|
||||||
|
m_pMonitor = pMonitor;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CHyprMonitorDebugOverlay::renderDataNoOverlay(SMonitor* pMonitor, float µs) {
|
||||||
|
m_dLastRenderTimesNoOverlay.push_back(µs / 1000.f);
|
||||||
|
|
||||||
|
if (m_dLastRenderTimesNoOverlay.size() > (long unsigned int)pMonitor->refreshRate)
|
||||||
|
m_dLastRenderTimesNoOverlay.pop_front();
|
||||||
|
|
||||||
|
if (!m_pMonitor)
|
||||||
|
m_pMonitor = pMonitor;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CHyprMonitorDebugOverlay::frameData(SMonitor* pMonitor) {
|
||||||
|
m_dLastFrametimes.push_back(std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now() - m_tpLastFrame).count() / 1000.f);
|
||||||
|
|
||||||
|
if (m_dLastFrametimes.size() > (long unsigned int)pMonitor->refreshRate)
|
||||||
|
m_dLastFrametimes.pop_front();
|
||||||
|
|
||||||
|
m_tpLastFrame = std::chrono::high_resolution_clock::now();
|
||||||
|
|
||||||
|
if (!m_pMonitor)
|
||||||
|
m_pMonitor = pMonitor;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CHyprMonitorDebugOverlay::draw(int offset) {
|
||||||
|
|
||||||
|
if (!m_pMonitor)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
int yOffset = offset;
|
||||||
|
cairo_text_extents_t cairoExtents;
|
||||||
|
float maxX = 0;
|
||||||
|
std::string text = "";
|
||||||
|
|
||||||
|
// get avg fps
|
||||||
|
float avgFrametime = 0;
|
||||||
|
for (auto& ft : m_dLastFrametimes) {
|
||||||
|
avgFrametime += ft;
|
||||||
|
}
|
||||||
|
avgFrametime /= m_dLastFrametimes.size() == 0 ? 1 : m_dLastFrametimes.size();
|
||||||
|
|
||||||
|
float avgRenderTime = 0;
|
||||||
|
for (auto& rt : m_dLastRenderTimes) {
|
||||||
|
avgRenderTime += rt;
|
||||||
|
}
|
||||||
|
avgRenderTime /= m_dLastRenderTimes.size() == 0 ? 1 : m_dLastRenderTimes.size();
|
||||||
|
|
||||||
|
float avgRenderTimeNoOverlay = 0;
|
||||||
|
for (auto& rt : m_dLastRenderTimesNoOverlay) {
|
||||||
|
avgRenderTimeNoOverlay += rt;
|
||||||
|
}
|
||||||
|
avgRenderTimeNoOverlay /= m_dLastRenderTimes.size() == 0 ? 1 : m_dLastRenderTimes.size();
|
||||||
|
|
||||||
|
const float FPS = 1.f / (avgFrametime / 1000.f); // frametimes are in ms
|
||||||
|
const float idealFPS = m_dLastFrametimes.size();
|
||||||
|
|
||||||
|
cairo_select_font_face(g_pDebugOverlay->m_pCairo, "Noto Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
|
||||||
|
|
||||||
|
cairo_set_font_size(g_pDebugOverlay->m_pCairo, 10);
|
||||||
|
cairo_set_source_rgba(g_pDebugOverlay->m_pCairo, 1.f, 1.f, 1.f, 1.f);
|
||||||
|
|
||||||
|
yOffset += 10;
|
||||||
|
cairo_move_to(g_pDebugOverlay->m_pCairo, 0, yOffset);
|
||||||
|
text = m_pMonitor->szName;
|
||||||
|
cairo_show_text(g_pDebugOverlay->m_pCairo, text.c_str());
|
||||||
|
cairo_text_extents(g_pDebugOverlay->m_pCairo, text.c_str(), &cairoExtents);
|
||||||
|
if (cairoExtents.width > maxX) maxX = cairoExtents.width;
|
||||||
|
|
||||||
|
cairo_set_font_size(g_pDebugOverlay->m_pCairo, 16);
|
||||||
|
|
||||||
|
if (FPS > idealFPS * 0.95f)
|
||||||
|
cairo_set_source_rgba(g_pDebugOverlay->m_pCairo, 0.2f, 1.f, 0.2f, 1.f);
|
||||||
|
else if (FPS > idealFPS * 0.8f)
|
||||||
|
cairo_set_source_rgba(g_pDebugOverlay->m_pCairo, 1.f, 1.f, 0.2f, 1.f);
|
||||||
|
else
|
||||||
|
cairo_set_source_rgba(g_pDebugOverlay->m_pCairo, 1.f, 0.2f, 0.2f, 1.f);
|
||||||
|
|
||||||
|
yOffset += 17;
|
||||||
|
cairo_move_to(g_pDebugOverlay->m_pCairo, 0, yOffset);
|
||||||
|
text = std::string(std::to_string((int)FPS) + " FPS");
|
||||||
|
cairo_show_text(g_pDebugOverlay->m_pCairo, text.c_str());
|
||||||
|
cairo_text_extents(g_pDebugOverlay->m_pCairo, text.c_str(), &cairoExtents);
|
||||||
|
if (cairoExtents.width > maxX) maxX = cairoExtents.width;
|
||||||
|
|
||||||
|
cairo_set_font_size(g_pDebugOverlay->m_pCairo, 10);
|
||||||
|
cairo_set_source_rgba(g_pDebugOverlay->m_pCairo, 1.f, 1.f, 1.f, 1.f);
|
||||||
|
|
||||||
|
yOffset += 11;
|
||||||
|
cairo_move_to(g_pDebugOverlay->m_pCairo, 0, yOffset);
|
||||||
|
text = std::string("Avg Frametime: " + std::to_string((int)avgFrametime) + "." + std::to_string((int)(avgFrametime * 10.f) % 10) + "ms");
|
||||||
|
cairo_show_text(g_pDebugOverlay->m_pCairo, text.c_str());
|
||||||
|
cairo_text_extents(g_pDebugOverlay->m_pCairo, text.c_str(), &cairoExtents);
|
||||||
|
if (cairoExtents.width > maxX) maxX = cairoExtents.width;
|
||||||
|
|
||||||
|
yOffset += 11;
|
||||||
|
cairo_move_to(g_pDebugOverlay->m_pCairo, 0, yOffset);
|
||||||
|
text = std::string("Avg Rendertime: " + std::to_string((int)avgRenderTime) + "." + std::to_string((int)(avgRenderTime * 10.f) % 10) + "ms");
|
||||||
|
cairo_show_text(g_pDebugOverlay->m_pCairo, text.c_str());
|
||||||
|
cairo_text_extents(g_pDebugOverlay->m_pCairo, text.c_str(), &cairoExtents);
|
||||||
|
if (cairoExtents.width > maxX) maxX = cairoExtents.width;
|
||||||
|
|
||||||
|
yOffset += 11;
|
||||||
|
cairo_move_to(g_pDebugOverlay->m_pCairo, 0, yOffset);
|
||||||
|
text = std::string("Avg Rendertime (no overlay): " + std::to_string((int)avgRenderTimeNoOverlay) + "." + std::to_string((int)(avgRenderTimeNoOverlay * 10.f) % 10) + "ms");
|
||||||
|
cairo_show_text(g_pDebugOverlay->m_pCairo, text.c_str());
|
||||||
|
cairo_text_extents(g_pDebugOverlay->m_pCairo, text.c_str(), &cairoExtents);
|
||||||
|
if (cairoExtents.width > maxX) maxX = cairoExtents.width;
|
||||||
|
|
||||||
|
yOffset += 11;
|
||||||
|
|
||||||
|
g_pHyprRenderer->damageBox(&m_wbLastDrawnBox);
|
||||||
|
m_wbLastDrawnBox = {(int)g_pCompositor->m_lMonitors.front().vecPosition.x, (int)g_pCompositor->m_lMonitors.front().vecPosition.y + offset - 1, (int)maxX + 2, yOffset - offset + 2};
|
||||||
|
g_pHyprRenderer->damageBox(&m_wbLastDrawnBox);
|
||||||
|
|
||||||
|
return yOffset - offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CHyprDebugOverlay::renderData(SMonitor* pMonitor, float µs) {
|
||||||
|
m_mMonitorOverlays[pMonitor].renderData(pMonitor, µs);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CHyprDebugOverlay::renderDataNoOverlay(SMonitor* pMonitor, float µs) {
|
||||||
|
m_mMonitorOverlays[pMonitor].renderDataNoOverlay(pMonitor, µs);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CHyprDebugOverlay::frameData(SMonitor* pMonitor) {
|
||||||
|
m_mMonitorOverlays[pMonitor].frameData(pMonitor);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CHyprDebugOverlay::draw() {
|
||||||
|
|
||||||
|
const auto PMONITOR = &g_pCompositor->m_lMonitors.front();
|
||||||
|
|
||||||
|
if (!m_pCairoSurface || !m_pCairo) {
|
||||||
|
m_pCairoSurface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, PMONITOR->vecSize.x, PMONITOR->vecSize.y);
|
||||||
|
m_pCairo = cairo_create(m_pCairoSurface);
|
||||||
|
}
|
||||||
|
|
||||||
|
// clear the pixmap
|
||||||
|
cairo_save(m_pCairo);
|
||||||
|
cairo_set_operator(m_pCairo, CAIRO_OPERATOR_CLEAR);
|
||||||
|
cairo_paint(m_pCairo);
|
||||||
|
cairo_restore(m_pCairo);
|
||||||
|
|
||||||
|
// draw the things
|
||||||
|
int offsetY = 0;
|
||||||
|
for (auto& m : g_pCompositor->m_lMonitors) {
|
||||||
|
offsetY += m_mMonitorOverlays[&m].draw(offsetY);
|
||||||
|
offsetY += 5; // for padding between mons
|
||||||
|
}
|
||||||
|
|
||||||
|
cairo_surface_flush(m_pCairoSurface);
|
||||||
|
|
||||||
|
// copy the data to an OpenGL texture we have
|
||||||
|
const auto DATA = cairo_image_surface_get_data(m_pCairoSurface);
|
||||||
|
m_tTexture.allocate();
|
||||||
|
glBindTexture(GL_TEXTURE_2D, m_tTexture.m_iTexID);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
|
|
||||||
|
#ifndef GLES2
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_BLUE);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, PMONITOR->vecSize.x, PMONITOR->vecSize.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, DATA);
|
||||||
|
|
||||||
|
wlr_box pMonBox = {0,0,PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y};
|
||||||
|
g_pHyprOpenGL->renderTexture(m_tTexture, &pMonBox, 255.f);
|
||||||
|
}
|
47
src/debug/HyprDebugOverlay.hpp
Normal file
47
src/debug/HyprDebugOverlay.hpp
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../defines.hpp"
|
||||||
|
#include "../helpers/Monitor.hpp"
|
||||||
|
#include "../render/Texture.hpp"
|
||||||
|
#include <deque>
|
||||||
|
#include <cairo/cairo.h>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
class CHyprMonitorDebugOverlay {
|
||||||
|
public:
|
||||||
|
int draw(int offset);
|
||||||
|
|
||||||
|
void renderData(SMonitor* pMonitor, float µs);
|
||||||
|
void renderDataNoOverlay(SMonitor* pMonitor, float µs);
|
||||||
|
void frameData(SMonitor* pMonitor);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::deque<float> m_dLastFrametimes;
|
||||||
|
std::deque<float> m_dLastRenderTimes;
|
||||||
|
std::deque<float> m_dLastRenderTimesNoOverlay;
|
||||||
|
std::chrono::high_resolution_clock::time_point m_tpLastFrame;
|
||||||
|
SMonitor* m_pMonitor = nullptr;
|
||||||
|
wlr_box m_wbLastDrawnBox;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CHyprDebugOverlay {
|
||||||
|
public:
|
||||||
|
|
||||||
|
void draw();
|
||||||
|
void renderData(SMonitor*, float µs);
|
||||||
|
void renderDataNoOverlay(SMonitor*, float µs);
|
||||||
|
void frameData(SMonitor*);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
std::unordered_map<SMonitor*, CHyprMonitorDebugOverlay> m_mMonitorOverlays;
|
||||||
|
|
||||||
|
cairo_surface_t* m_pCairoSurface = nullptr;
|
||||||
|
cairo_t* m_pCairo = nullptr;
|
||||||
|
|
||||||
|
CTexture m_tTexture;
|
||||||
|
|
||||||
|
friend class CHyprMonitorDebugOverlay;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline std::unique_ptr<CHyprDebugOverlay> g_pDebugOverlay;
|
@@ -1,15 +1,22 @@
|
|||||||
#include "Log.hpp"
|
#include "Log.hpp"
|
||||||
#include "../defines.hpp"
|
#include "../defines.hpp"
|
||||||
|
#include "../Compositor.hpp"
|
||||||
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
void Debug::init(std::string IS) {
|
||||||
|
if (ISDEBUG)
|
||||||
|
logFile = "/tmp/hypr/" + IS + "/hyprlandd.log";
|
||||||
|
else
|
||||||
|
logFile = "/tmp/hypr/" + IS + "/hyprland.log";
|
||||||
|
}
|
||||||
|
|
||||||
void Debug::log(LogLevel level, const char* fmt, ...) {
|
void Debug::log(LogLevel level, const char* fmt, ...) {
|
||||||
|
|
||||||
// log to a file
|
// log to a file
|
||||||
const std::string DEBUGPATH = ISDEBUG ? "/tmp/hypr/hyprlandd.log" : "/tmp/hypr/hyprland.log";
|
|
||||||
std::ofstream ofs;
|
std::ofstream ofs;
|
||||||
ofs.open(DEBUGPATH, std::ios::out | std::ios::app);
|
ofs.open(logFile, std::ios::out | std::ios::app);
|
||||||
|
|
||||||
switch (level) {
|
switch (level) {
|
||||||
case LOG:
|
case LOG:
|
||||||
|
@@ -12,5 +12,8 @@ enum LogLevel {
|
|||||||
};
|
};
|
||||||
|
|
||||||
namespace Debug {
|
namespace Debug {
|
||||||
|
void init(std::string IS);
|
||||||
void log(LogLevel level, const char* fmt, ...);
|
void log(LogLevel level, const char* fmt, ...);
|
||||||
|
|
||||||
|
inline std::string logFile;
|
||||||
};
|
};
|
@@ -65,3 +65,5 @@
|
|||||||
#ifndef GIT_DIRTY
|
#ifndef GIT_DIRTY
|
||||||
#define GIT_DIRTY "?"
|
#define GIT_DIRTY "?"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define SPECIAL_WORKSPACE_ID -99
|
@@ -109,4 +109,7 @@ namespace Events {
|
|||||||
|
|
||||||
// Deco XDG
|
// Deco XDG
|
||||||
LISTENER(NewXDGDeco);
|
LISTENER(NewXDGDeco);
|
||||||
|
|
||||||
|
// Renderer destroy
|
||||||
|
LISTENER(RendererDestroy);
|
||||||
};
|
};
|
@@ -58,7 +58,12 @@ void Events::listener_destroyLayerSurface(void* owner, void* data) {
|
|||||||
|
|
||||||
Debug::log(LOG, "LayerSurface %x destroyed", layersurface->layerSurface);
|
Debug::log(LOG, "LayerSurface %x destroyed", layersurface->layerSurface);
|
||||||
|
|
||||||
if (!layersurface->fadingOut) {
|
const auto PMONITOR = g_pCompositor->getMonitorFromID(layersurface->monitorID);
|
||||||
|
|
||||||
|
if (!g_pCompositor->getMonitorFromID(layersurface->monitorID))
|
||||||
|
Debug::log(WARN, "Layersurface destroyed on an invalid monitor (removed?)");
|
||||||
|
|
||||||
|
if (!layersurface->fadingOut && PMONITOR) {
|
||||||
Debug::log(LOG, "Removing LayerSurface that wasn't mapped.");
|
Debug::log(LOG, "Removing LayerSurface that wasn't mapped.");
|
||||||
layersurface->alpha.setValueAndWarp(0.f);
|
layersurface->alpha.setValueAndWarp(0.f);
|
||||||
layersurface->fadingOut = true;
|
layersurface->fadingOut = true;
|
||||||
@@ -70,8 +75,6 @@ void Events::listener_destroyLayerSurface(void* owner, void* data) {
|
|||||||
layersurface->hyprListener_unmapLayerSurface.removeCallback();
|
layersurface->hyprListener_unmapLayerSurface.removeCallback();
|
||||||
layersurface->hyprListener_newPopup.removeCallback();
|
layersurface->hyprListener_newPopup.removeCallback();
|
||||||
|
|
||||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(layersurface->monitorID);
|
|
||||||
|
|
||||||
// rearrange to fix the reserved areas
|
// rearrange to fix the reserved areas
|
||||||
if (PMONITOR) {
|
if (PMONITOR) {
|
||||||
g_pHyprRenderer->arrangeLayersForMonitor(PMONITOR->ID);
|
g_pHyprRenderer->arrangeLayersForMonitor(PMONITOR->ID);
|
||||||
@@ -131,6 +134,11 @@ void Events::listener_unmapLayerSurface(void* owner, void* data) {
|
|||||||
|
|
||||||
Debug::log(LOG, "LayerSurface %x unmapped", layersurface->layerSurface);
|
Debug::log(LOG, "LayerSurface %x unmapped", layersurface->layerSurface);
|
||||||
|
|
||||||
|
if (!g_pCompositor->getMonitorFromID(layersurface->monitorID)) {
|
||||||
|
Debug::log(WARN, "Layersurface unmapping on invalid monitor (removed?) ignoring.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// make a snapshot and start fade
|
// make a snapshot and start fade
|
||||||
g_pHyprOpenGL->makeLayerSnapshot(layersurface);
|
g_pHyprOpenGL->makeLayerSnapshot(layersurface);
|
||||||
layersurface->alpha = 0.f;
|
layersurface->alpha = 0.f;
|
||||||
@@ -152,6 +160,12 @@ void Events::listener_unmapLayerSurface(void* owner, void* data) {
|
|||||||
|
|
||||||
wlr_box geomFixed = {layersurface->geometry.x + PMONITOR->vecPosition.x, layersurface->geometry.y + PMONITOR->vecPosition.y, layersurface->geometry.width, layersurface->geometry.height};
|
wlr_box geomFixed = {layersurface->geometry.x + PMONITOR->vecPosition.x, layersurface->geometry.y + PMONITOR->vecPosition.y, layersurface->geometry.width, layersurface->geometry.height};
|
||||||
g_pHyprRenderer->damageBox(&geomFixed);
|
g_pHyprRenderer->damageBox(&geomFixed);
|
||||||
|
|
||||||
|
geomFixed = {layersurface->geometry.x + (int)PMONITOR->vecPosition.x, layersurface->geometry.y + (int)PMONITOR->vecPosition.y, (int)layersurface->layerSurface->surface->current.width, (int)layersurface->layerSurface->surface->current.height};
|
||||||
|
g_pHyprRenderer->damageBox(&geomFixed);
|
||||||
|
|
||||||
|
geomFixed = {layersurface->geometry.x, layersurface->geometry.y, (int)layersurface->layerSurface->surface->current.width, (int)layersurface->layerSurface->surface->current.height};
|
||||||
|
layersurface->geometry = geomFixed; // because the surface can overflow... for some reason?
|
||||||
}
|
}
|
||||||
|
|
||||||
void Events::listener_commitLayerSurface(void* owner, void* data) {
|
void Events::listener_commitLayerSurface(void* owner, void* data) {
|
||||||
|
@@ -153,4 +153,8 @@ void Events::listener_InhibitDeactivate(wl_listener* listener, void* data) {
|
|||||||
|
|
||||||
g_pCompositor->m_sSeat.exclusiveClient = nullptr;
|
g_pCompositor->m_sSeat.exclusiveClient = nullptr;
|
||||||
g_pInputManager->refocus();
|
g_pInputManager->refocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Events::listener_RendererDestroy(wl_listener* listener, void* data) {
|
||||||
|
Debug::log(LOG, "!!Renderer destroyed!!");
|
||||||
}
|
}
|
@@ -48,6 +48,16 @@ void Events::listener_newOutput(wl_listener* listener, void* data) {
|
|||||||
// new monitor added, let's accomodate for that.
|
// new monitor added, let's accomodate for that.
|
||||||
const auto OUTPUT = (wlr_output*)data;
|
const auto OUTPUT = (wlr_output*)data;
|
||||||
|
|
||||||
|
if (!OUTPUT->name) {
|
||||||
|
Debug::log(ERR, "New monitor has no name?? Ignoring");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g_pCompositor->getMonitorFromName(std::string(OUTPUT->name))) {
|
||||||
|
Debug::log(WARN, "Monitor with name %s already exists, not adding as new!", OUTPUT->name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// get monitor rule that matches
|
// get monitor rule that matches
|
||||||
SMonitorRule monitorRule = g_pConfigManager->getMonitorRuleFor(OUTPUT->name);
|
SMonitorRule monitorRule = g_pConfigManager->getMonitorRuleFor(OUTPUT->name);
|
||||||
|
|
||||||
@@ -55,12 +65,16 @@ void Events::listener_newOutput(wl_listener* listener, void* data) {
|
|||||||
if (monitorRule.disabled) {
|
if (monitorRule.disabled) {
|
||||||
wlr_output_enable(OUTPUT, 0);
|
wlr_output_enable(OUTPUT, 0);
|
||||||
wlr_output_commit(OUTPUT);
|
wlr_output_commit(OUTPUT);
|
||||||
|
|
||||||
|
if (const auto PMONITOR = g_pCompositor->getMonitorFromName(std::string(OUTPUT->name)); PMONITOR) {
|
||||||
|
listener_monitorDestroy(nullptr, PMONITOR->output);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SMonitor newMonitor;
|
SMonitor newMonitor;
|
||||||
newMonitor.output = OUTPUT;
|
newMonitor.output = OUTPUT;
|
||||||
newMonitor.ID = g_pCompositor->m_lMonitors.size();
|
newMonitor.ID = g_pCompositor->getNextAvailableMonitorID();
|
||||||
newMonitor.szName = OUTPUT->name;
|
newMonitor.szName = OUTPUT->name;
|
||||||
|
|
||||||
wlr_output_init_render(OUTPUT, g_pCompositor->m_sWLRAllocator, g_pCompositor->m_sWLRRenderer);
|
wlr_output_init_render(OUTPUT, g_pCompositor->m_sWLRAllocator, g_pCompositor->m_sWLRRenderer);
|
||||||
@@ -101,17 +115,26 @@ void Events::listener_newOutput(wl_listener* listener, void* data) {
|
|||||||
|
|
||||||
// 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;
|
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;
|
||||||
g_pCompositor->m_lWorkspaces.emplace_back(newMonitor.ID);
|
|
||||||
const auto PNEWWORKSPACE = &g_pCompositor->m_lWorkspaces.back();
|
auto PNEWWORKSPACE = g_pCompositor->getWorkspaceByID(WORKSPACEID);
|
||||||
|
|
||||||
// We are required to set the name here immediately
|
Debug::log(LOG, "New monitor: WORKSPACEID %d, exists: %d", WORKSPACEID, (int)(PNEWWORKSPACE != nullptr));
|
||||||
wlr_ext_workspace_handle_v1_set_name(PNEWWORKSPACE->m_pWlrHandle, std::to_string(WORKSPACEID).c_str());
|
|
||||||
|
if (PNEWWORKSPACE) {
|
||||||
|
// workspace exists, move it to the newly connected monitor
|
||||||
|
g_pCompositor->moveWorkspaceToMonitor(PNEWWORKSPACE, PNEWMONITOR);
|
||||||
|
} else {
|
||||||
|
g_pCompositor->m_lWorkspaces.emplace_back(newMonitor.ID);
|
||||||
|
PNEWWORKSPACE = &g_pCompositor->m_lWorkspaces.back();
|
||||||
|
|
||||||
PNEWWORKSPACE->m_iID = WORKSPACEID;
|
// We are required to set the name here immediately
|
||||||
PNEWWORKSPACE->m_szName = std::to_string(WORKSPACEID);
|
wlr_ext_workspace_handle_v1_set_name(PNEWWORKSPACE->m_pWlrHandle, std::to_string(WORKSPACEID).c_str());
|
||||||
|
|
||||||
|
PNEWWORKSPACE->m_iID = WORKSPACEID;
|
||||||
|
PNEWWORKSPACE->m_szName = std::to_string(WORKSPACEID);
|
||||||
|
}
|
||||||
|
|
||||||
PNEWMONITOR->activeWorkspace = PNEWWORKSPACE->m_iID;
|
PNEWMONITOR->activeWorkspace = PNEWWORKSPACE->m_iID;
|
||||||
|
|
||||||
PNEWMONITOR->scale = monitorRule.scale;
|
PNEWMONITOR->scale = monitorRule.scale;
|
||||||
|
|
||||||
g_pCompositor->deactivateAllWLRWorkspaces(PNEWWORKSPACE->m_pWlrHandle);
|
g_pCompositor->deactivateAllWLRWorkspaces(PNEWWORKSPACE->m_pWlrHandle);
|
||||||
@@ -122,7 +145,9 @@ void Events::listener_newOutput(wl_listener* listener, void* data) {
|
|||||||
//
|
//
|
||||||
|
|
||||||
if (!g_pCompositor->m_pLastMonitor) // set the last monitor if it isnt set yet
|
if (!g_pCompositor->m_pLastMonitor) // set the last monitor if it isnt set yet
|
||||||
g_pCompositor->m_pLastMonitor = PNEWMONITOR;
|
g_pCompositor->m_pLastMonitor = PNEWMONITOR;
|
||||||
|
|
||||||
|
g_pEventManager->postEvent(SHyprIPCEvent("monitoradded", PNEWMONITOR->szName));
|
||||||
|
|
||||||
// ready to process cuz we have a monitor
|
// ready to process cuz we have a monitor
|
||||||
g_pCompositor->m_bReadyToProcess = true;
|
g_pCompositor->m_bReadyToProcess = true;
|
||||||
@@ -131,6 +156,15 @@ void Events::listener_newOutput(wl_listener* listener, void* data) {
|
|||||||
void Events::listener_monitorFrame(void* owner, void* data) {
|
void Events::listener_monitorFrame(void* owner, void* data) {
|
||||||
SMonitor* const PMONITOR = (SMonitor*)owner;
|
SMonitor* const PMONITOR = (SMonitor*)owner;
|
||||||
|
|
||||||
|
static std::chrono::high_resolution_clock::time_point startRender = 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();
|
||||||
|
|
||||||
|
if (g_pConfigManager->getInt("debug:overlay") == 1) {
|
||||||
|
startRender = std::chrono::high_resolution_clock::now();
|
||||||
|
g_pDebugOverlay->frameData(PMONITOR);
|
||||||
|
}
|
||||||
|
|
||||||
// Hack: only check when monitor with top hz refreshes, saves a bit of resources.
|
// Hack: only check when monitor with top hz refreshes, saves a bit of resources.
|
||||||
// This is for stuff that should be run every frame
|
// This is for stuff that should be run every frame
|
||||||
if (PMONITOR->ID == pMostHzMonitor->ID) {
|
if (PMONITOR->ID == pMostHzMonitor->ID) {
|
||||||
@@ -146,9 +180,14 @@ void Events::listener_monitorFrame(void* owner, void* data) {
|
|||||||
g_pConfigManager->performMonitorReload();
|
g_pConfigManager->performMonitorReload();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PMONITOR->needsFrameSkip) {
|
if (PMONITOR->framesToSkip > 0) {
|
||||||
PMONITOR->needsFrameSkip = false;
|
PMONITOR->framesToSkip -= 1;
|
||||||
wlr_output_schedule_frame(PMONITOR->output);
|
|
||||||
|
if (!PMONITOR->noFrameSchedule)
|
||||||
|
wlr_output_schedule_frame(PMONITOR->output);
|
||||||
|
else {
|
||||||
|
Debug::log(LOG, "NoFrameSchedule hit for %s.", PMONITOR->szName.c_str());
|
||||||
|
}
|
||||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PMONITOR->ID);
|
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PMONITOR->ID);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -182,7 +221,7 @@ 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 (DTMODE == DAMAGE_TRACKING_NONE || DTMODE == DAMAGE_TRACKING_MONITOR) {
|
||||||
pixman_region32_union_rect(&damage, &damage, 0, 0, (int)PMONITOR->vecPixelSize.x, (int)PMONITOR->vecPixelSize.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 {
|
||||||
@@ -213,6 +252,17 @@ void Events::listener_monitorFrame(void* owner, void* data) {
|
|||||||
|
|
||||||
g_pHyprRenderer->renderAllClientsForMonitor(PMONITOR->ID, &now);
|
g_pHyprRenderer->renderAllClientsForMonitor(PMONITOR->ID, &now);
|
||||||
|
|
||||||
|
// if correct monitor draw hyprerror
|
||||||
|
if (PMONITOR->ID == 0)
|
||||||
|
g_pHyprError->draw();
|
||||||
|
|
||||||
|
// for drawing the debug overlay
|
||||||
|
if (PMONITOR->ID == 0 && g_pConfigManager->getInt("debug:overlay") == 1) {
|
||||||
|
startRenderOverlay = std::chrono::high_resolution_clock::now();
|
||||||
|
g_pDebugOverlay->draw();
|
||||||
|
endRenderOverlay = std::chrono::high_resolution_clock::now();
|
||||||
|
}
|
||||||
|
|
||||||
wlr_renderer_begin(g_pCompositor->m_sWLRRenderer, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y);
|
wlr_renderer_begin(g_pCompositor->m_sWLRRenderer, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y);
|
||||||
|
|
||||||
wlr_output_render_software_cursors(PMONITOR->output, NULL);
|
wlr_output_render_software_cursors(PMONITOR->output, NULL);
|
||||||
@@ -226,10 +276,10 @@ void Events::listener_monitorFrame(void* owner, void* data) {
|
|||||||
pixman_region32_init(&frameDamage);
|
pixman_region32_init(&frameDamage);
|
||||||
|
|
||||||
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->vecPixelSize.x, (int)PMONITOR->vecPixelSize.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 (DTMODE == DAMAGE_TRACKING_NONE || DTMODE == DAMAGE_TRACKING_MONITOR)
|
||||||
pixman_region32_union_rect(&frameDamage, &frameDamage, 0, 0, (int)PMONITOR->vecPixelSize.x, (int)PMONITOR->vecPixelSize.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);
|
||||||
pixman_region32_fini(&frameDamage);
|
pixman_region32_fini(&frameDamage);
|
||||||
@@ -238,6 +288,17 @@ void Events::listener_monitorFrame(void* owner, void* data) {
|
|||||||
wlr_output_commit(PMONITOR->output);
|
wlr_output_commit(PMONITOR->output);
|
||||||
|
|
||||||
wlr_output_schedule_frame(PMONITOR->output);
|
wlr_output_schedule_frame(PMONITOR->output);
|
||||||
|
|
||||||
|
if (g_pConfigManager->getInt("debug:overlay") == 1) {
|
||||||
|
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);
|
||||||
|
if (PMONITOR->ID == 0) {
|
||||||
|
const float µsNoOverlay = µs - std::chrono::duration_cast<std::chrono::nanoseconds>(endRenderOverlay - startRenderOverlay).count() / 1000.f;
|
||||||
|
g_pDebugOverlay->renderDataNoOverlay(PMONITOR, µsNoOverlay);
|
||||||
|
} else {
|
||||||
|
g_pDebugOverlay->renderDataNoOverlay(PMONITOR, µs);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Events::listener_monitorDestroy(void* owner, void* data) {
|
void Events::listener_monitorDestroy(void* owner, void* data) {
|
||||||
@@ -255,7 +316,58 @@ void Events::listener_monitorDestroy(void* owner, void* data) {
|
|||||||
if (!pMonitor)
|
if (!pMonitor)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// Cleanup everything. Move windows back, snap cursor, shit.
|
||||||
|
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) {
|
||||||
|
Debug::log(CRIT, "No monitors! Unplugged last! Exiting.");
|
||||||
|
g_pCompositor->cleanupExit();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
// move workspaces
|
||||||
|
std::deque<CWorkspace*> wspToMove;
|
||||||
|
for (auto& w : g_pCompositor->m_lWorkspaces) {
|
||||||
|
if (w.m_iMonitorID == pMonitor->ID) {
|
||||||
|
wspToMove.push_back(&w);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& w : wspToMove) {
|
||||||
|
g_pCompositor->moveWorkspaceToMonitor(w, BACKUPMON);
|
||||||
|
w->startAnim(true, true, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
pMonitor->activeWorkspace = -1;
|
||||||
|
|
||||||
|
for (auto it = g_pCompositor->m_lWorkspaces.begin(); it != g_pCompositor->m_lWorkspaces.end(); ++it) {
|
||||||
|
if (it->m_iMonitorID == pMonitor->ID) {
|
||||||
|
it = g_pCompositor->m_lWorkspaces.erase(it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Debug::log(LOG, "Removed monitor %s!", pMonitor->szName.c_str());
|
||||||
|
|
||||||
|
g_pEventManager->postEvent(SHyprIPCEvent("monitorremoved", pMonitor->szName));
|
||||||
|
|
||||||
g_pCompositor->m_lMonitors.remove(*pMonitor);
|
g_pCompositor->m_lMonitors.remove(*pMonitor);
|
||||||
|
|
||||||
// TODO: cleanup windows
|
// update the pMostHzMonitor
|
||||||
|
if (pMostHzMonitor == pMonitor) {
|
||||||
|
int mostHz = 0;
|
||||||
|
SMonitor* pMonitorMostHz = nullptr;
|
||||||
|
|
||||||
|
for (auto& m : g_pCompositor->m_lMonitors) {
|
||||||
|
if (m.refreshRate > mostHz) {
|
||||||
|
pMonitorMostHz = &m;
|
||||||
|
mostHz = m.refreshRate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pMostHzMonitor = pMonitorMostHz;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -23,8 +23,8 @@ void addPopupGlobalCoords(void* pPopup, int* x, int* y) {
|
|||||||
|
|
||||||
auto curPopup = PPOPUP;
|
auto curPopup = PPOPUP;
|
||||||
while (true) {
|
while (true) {
|
||||||
px += curPopup->popup->geometry.x;
|
px += curPopup->popup->current.geometry.x;
|
||||||
py += curPopup->popup->geometry.y;
|
py += curPopup->popup->current.geometry.y;
|
||||||
|
|
||||||
if (curPopup->parentPopup) {
|
if (curPopup->parentPopup) {
|
||||||
curPopup = curPopup->parentPopup;
|
curPopup = curPopup->parentPopup;
|
||||||
@@ -134,7 +134,7 @@ void Events::listener_mapPopupXDG(void* owner, void* data) {
|
|||||||
|
|
||||||
Debug::log(LOG, "New XDG Popup mapped at %d %d", (int)PPOPUP->lx, (int)PPOPUP->ly);
|
Debug::log(LOG, "New XDG Popup mapped at %d %d", (int)PPOPUP->lx, (int)PPOPUP->ly);
|
||||||
|
|
||||||
PPOPUP->pSurfaceTree = SubsurfaceTree::createTreeRoot(PPOPUP->popup->base->surface, addPopupGlobalCoords, PPOPUP);
|
PPOPUP->pSurfaceTree = SubsurfaceTree::createTreeRoot(PPOPUP->popup->base->surface, addPopupGlobalCoords, PPOPUP, PPOPUP->parentWindow);
|
||||||
|
|
||||||
Debug::log(LOG, "XDG Popup got assigned a surfaceTreeNode %x", PPOPUP->pSurfaceTree);
|
Debug::log(LOG, "XDG Popup got assigned a surfaceTreeNode %x", PPOPUP->pSurfaceTree);
|
||||||
}
|
}
|
||||||
|
@@ -25,16 +25,24 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
|||||||
CWindow* PWINDOW = (CWindow*)owner;
|
CWindow* PWINDOW = (CWindow*)owner;
|
||||||
|
|
||||||
const auto PMONITOR = g_pCompositor->getMonitorFromCursor();
|
const auto PMONITOR = g_pCompositor->getMonitorFromCursor();
|
||||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(PMONITOR->activeWorkspace);
|
const auto PWORKSPACE = PMONITOR->specialWorkspaceOpen ? g_pCompositor->getWorkspaceByID(SPECIAL_WORKSPACE_ID) : g_pCompositor->getWorkspaceByID(PMONITOR->activeWorkspace);
|
||||||
PWINDOW->m_iMonitorID = PMONITOR->ID;
|
PWINDOW->m_iMonitorID = PMONITOR->ID;
|
||||||
PWINDOW->m_bMappedX11 = true;
|
PWINDOW->m_bMappedX11 = true;
|
||||||
PWINDOW->m_iWorkspaceID = PMONITOR->activeWorkspace;
|
PWINDOW->m_iWorkspaceID = PMONITOR->specialWorkspaceOpen ? SPECIAL_WORKSPACE_ID : PMONITOR->activeWorkspace;
|
||||||
PWINDOW->m_bIsMapped = true;
|
PWINDOW->m_bIsMapped = true;
|
||||||
PWINDOW->m_bReadyToDelete = false;
|
PWINDOW->m_bReadyToDelete = false;
|
||||||
PWINDOW->m_bFadingOut = false;
|
PWINDOW->m_bFadingOut = false;
|
||||||
PWINDOW->m_szTitle = g_pXWaylandManager->getTitle(PWINDOW);
|
PWINDOW->m_szTitle = g_pXWaylandManager->getTitle(PWINDOW);
|
||||||
PWINDOW->m_fAlpha = 255.f;
|
PWINDOW->m_fAlpha = 255.f;
|
||||||
|
|
||||||
|
// Set all windows tiled regardless of anything
|
||||||
|
g_pXWaylandManager->setWindowStyleTiled(PWINDOW, WLR_EDGE_LEFT | WLR_EDGE_RIGHT | WLR_EDGE_TOP | WLR_EDGE_BOTTOM);
|
||||||
|
|
||||||
|
// Foreign Toplevel
|
||||||
|
PWINDOW->m_phForeignToplevel = wlr_foreign_toplevel_handle_v1_create(g_pCompositor->m_sWLRToplevelMgr);
|
||||||
|
// TODO: handle foreign events (requests)
|
||||||
|
wlr_foreign_toplevel_handle_v1_set_app_id(PWINDOW->m_phForeignToplevel, g_pXWaylandManager->getAppIDClass(PWINDOW).c_str());
|
||||||
|
|
||||||
// checks if the window wants borders and sets the appriopriate flag
|
// checks if the window wants borders and sets the appriopriate flag
|
||||||
g_pXWaylandManager->checkBorders(PWINDOW);
|
g_pXWaylandManager->checkBorders(PWINDOW);
|
||||||
|
|
||||||
@@ -62,22 +70,29 @@ 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);
|
g_pLayoutManager->getCurrentLayout()->fullscreenRequestForWindow(PFULLWINDOW, FULLSCREEN_FULL);
|
||||||
g_pXWaylandManager->setWindowFullscreen(PFULLWINDOW, PFULLWINDOW->m_bIsFullscreen);
|
g_pXWaylandManager->setWindowFullscreen(PFULLWINDOW, PFULLWINDOW->m_bIsFullscreen);
|
||||||
}
|
}
|
||||||
|
|
||||||
// window rules
|
// window rules
|
||||||
const auto WINDOWRULES = g_pConfigManager->getMatchingRules(PWINDOW);
|
const auto WINDOWRULES = g_pConfigManager->getMatchingRules(PWINDOW);
|
||||||
|
std::string requestedWorkspace = "";
|
||||||
|
bool workspaceSilent = false;
|
||||||
|
|
||||||
for (auto& r : WINDOWRULES) {
|
for (auto& r : WINDOWRULES) {
|
||||||
if (r.szRule.find("monitor") == 0) {
|
if (r.szRule.find("monitor") == 0) {
|
||||||
try {
|
try {
|
||||||
const long int MONITOR = std::stoi(r.szRule.substr(r.szRule.find(" ")));
|
const auto MONITORSTR = r.szRule.substr(r.szRule.find(" "));
|
||||||
|
|
||||||
if (MONITOR >= (long int)g_pCompositor->m_lMonitors.size() || MONITOR < (long int)0)
|
if (MONITORSTR == "unset") {
|
||||||
PWINDOW->m_iMonitorID = 0;
|
PWINDOW->m_iMonitorID = PMONITOR->ID;
|
||||||
else
|
} else {
|
||||||
PWINDOW->m_iMonitorID = MONITOR;
|
const long int MONITOR = std::stoi(MONITORSTR);
|
||||||
|
if (MONITOR >= (long int)g_pCompositor->m_lMonitors.size() || MONITOR < (long int)0)
|
||||||
|
PWINDOW->m_iMonitorID = 0;
|
||||||
|
else
|
||||||
|
PWINDOW->m_iMonitorID = MONITOR;
|
||||||
|
}
|
||||||
|
|
||||||
PWINDOW->m_iWorkspaceID = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID)->activeWorkspace;
|
PWINDOW->m_iWorkspaceID = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID)->activeWorkspace;
|
||||||
|
|
||||||
@@ -86,11 +101,14 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
|||||||
Debug::log(ERR, "Rule monitor failed, rule: %s -> %s | err: %s", r.szRule.c_str(), r.szValue.c_str(), e.what());
|
Debug::log(ERR, "Rule monitor failed, rule: %s -> %s | err: %s", r.szRule.c_str(), r.szValue.c_str(), e.what());
|
||||||
}
|
}
|
||||||
} else if (r.szRule.find("workspace") == 0) {
|
} else if (r.szRule.find("workspace") == 0) {
|
||||||
// switch to workspace
|
// check if it isnt unset
|
||||||
g_pKeybindManager->m_mDispatchers["workspace"](r.szRule.substr(r.szRule.find_first_of(' ') + 1));
|
const auto WORKSPACERQ = r.szRule.substr(r.szRule.find_first_of(' ') + 1);
|
||||||
|
|
||||||
PWINDOW->m_iMonitorID = g_pCompositor->m_pLastMonitor->ID;
|
if (WORKSPACERQ == "unset") {
|
||||||
PWINDOW->m_iWorkspaceID = g_pCompositor->m_pLastMonitor->activeWorkspace;
|
requestedWorkspace = "";
|
||||||
|
} else {
|
||||||
|
requestedWorkspace = WORKSPACERQ;
|
||||||
|
}
|
||||||
|
|
||||||
Debug::log(LOG, "Rule workspace matched by window %x, %s applied.", PWINDOW, r.szValue.c_str());
|
Debug::log(LOG, "Rule workspace matched by window %x, %s applied.", PWINDOW, r.szValue.c_str());
|
||||||
} else if (r.szRule.find("float") == 0) {
|
} else if (r.szRule.find("float") == 0) {
|
||||||
@@ -101,9 +119,23 @@ 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.find("rounding") == 0) {
|
||||||
|
try {
|
||||||
|
PWINDOW->m_sAdditionalConfigData.rounding = std::stoi(r.szRule.substr(r.szRule.find_first_of(' ') + 1));
|
||||||
|
} catch (std::exception& e) {
|
||||||
|
Debug::log(ERR, "Rounding rule \"%s\" failed with: %s", r.szRule.c_str(), e.what());
|
||||||
|
}
|
||||||
} else if (r.szRule.find("opacity") == 0) {
|
} else if (r.szRule.find("opacity") == 0) {
|
||||||
try {
|
try {
|
||||||
PWINDOW->m_sSpecialRenderData.alpha = std::stof(r.szRule.substr(r.szRule.find_first_of(' ') + 1));
|
std::string alphaPart = r.szRule.substr(r.szRule.find_first_of(' ') + 1);
|
||||||
|
|
||||||
|
if (alphaPart.find_first_of(' ') != std::string::npos) {
|
||||||
|
// we have a comma, 2 values
|
||||||
|
PWINDOW->m_sSpecialRenderData.alpha = std::stof(alphaPart.substr(0, alphaPart.find_first_of(' ')));
|
||||||
|
PWINDOW->m_sSpecialRenderData.alphaInactive = std::stof(alphaPart.substr(alphaPart.find_first_of(' ') + 1));
|
||||||
|
} else {
|
||||||
|
PWINDOW->m_sSpecialRenderData.alpha = std::stof(alphaPart);
|
||||||
|
}
|
||||||
} catch(std::exception& e) {
|
} catch(std::exception& e) {
|
||||||
Debug::log(ERR, "Opacity rule \"%s\" failed with: %s", r.szRule.c_str(), e.what());
|
Debug::log(ERR, "Opacity rule \"%s\" failed with: %s", r.szRule.c_str(), e.what());
|
||||||
}
|
}
|
||||||
@@ -113,6 +145,25 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (requestedWorkspace != "") {
|
||||||
|
// process requested workspace
|
||||||
|
if (requestedWorkspace.find_first_of(' ') != std::string::npos) {
|
||||||
|
// check for silent
|
||||||
|
if (requestedWorkspace.find("silent") != std::string::npos) {
|
||||||
|
workspaceSilent = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
requestedWorkspace = requestedWorkspace.substr(0, requestedWorkspace.find_first_of(' '));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!workspaceSilent) {
|
||||||
|
g_pKeybindManager->m_mDispatchers["workspace"](requestedWorkspace);
|
||||||
|
|
||||||
|
PWINDOW->m_iMonitorID = g_pCompositor->m_pLastMonitor->ID;
|
||||||
|
PWINDOW->m_iWorkspaceID = g_pCompositor->m_pLastMonitor->activeWorkspace;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (PWINDOW->m_bIsFloating) {
|
if (PWINDOW->m_bIsFloating) {
|
||||||
g_pLayoutManager->getCurrentLayout()->onWindowCreatedFloating(PWINDOW);
|
g_pLayoutManager->getCurrentLayout()->onWindowCreatedFloating(PWINDOW);
|
||||||
PWINDOW->m_bCreatedOverFullscreen = true;
|
PWINDOW->m_bCreatedOverFullscreen = true;
|
||||||
@@ -167,7 +218,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
|||||||
if (!PWINDOW->m_bNoFocus)
|
if (!PWINDOW->m_bNoFocus)
|
||||||
g_pCompositor->focusWindow(PWINDOW);
|
g_pCompositor->focusWindow(PWINDOW);
|
||||||
|
|
||||||
PWINDOW->m_pSurfaceTree = SubsurfaceTree::createTreeRoot(g_pXWaylandManager->getWindowSurface(PWINDOW), addViewCoords, PWINDOW);
|
PWINDOW->m_pSurfaceTree = SubsurfaceTree::createTreeRoot(g_pXWaylandManager->getWindowSurface(PWINDOW), addViewCoords, PWINDOW, PWINDOW);
|
||||||
|
|
||||||
Debug::log(LOG, "Window got assigned a surfaceTreeNode %x", PWINDOW->m_pSurfaceTree);
|
Debug::log(LOG, "Window got assigned a surfaceTreeNode %x", PWINDOW->m_pSurfaceTree);
|
||||||
|
|
||||||
@@ -184,7 +235,16 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// do the animation thing
|
// do the animation thing
|
||||||
g_pAnimationManager->onWindowPostCreate(PWINDOW);
|
g_pAnimationManager->onWindowPostCreateClose(PWINDOW, false);
|
||||||
|
|
||||||
|
if (workspaceSilent) {
|
||||||
|
// move the window
|
||||||
|
if (g_pCompositor->m_pLastWindow == PWINDOW) {
|
||||||
|
g_pKeybindManager->m_mDispatchers["movetoworkspacesilent"](requestedWorkspace);
|
||||||
|
} else {
|
||||||
|
Debug::log(ERR, "Tried to set workspace silent rule to a nofocus window!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
@@ -244,6 +304,18 @@ void Events::listener_unmapWindow(void* owner, void* data) {
|
|||||||
g_pCompositor->m_lWindowsFadingOut.push_back(PWINDOW);
|
g_pCompositor->m_lWindowsFadingOut.push_back(PWINDOW);
|
||||||
|
|
||||||
g_pHyprRenderer->damageMonitor(g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID));
|
g_pHyprRenderer->damageMonitor(g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID));
|
||||||
|
|
||||||
|
// do the animation thing
|
||||||
|
PWINDOW->m_vOriginalClosedPos = PWINDOW->m_vRealPosition.vec();
|
||||||
|
PWINDOW->m_vOriginalClosedSize = PWINDOW->m_vRealSize.vec();
|
||||||
|
|
||||||
|
if (!PWINDOW->m_bX11DoesntWantBorders) // don't animate out if they weren't animated in.
|
||||||
|
PWINDOW->m_vRealPosition = PWINDOW->m_vRealPosition.vec() + Vector2D(0.01f, 0.01f); // it has to be animated, otherwise onWindowPostCreateClose will ignore it
|
||||||
|
g_pAnimationManager->onWindowPostCreateClose(PWINDOW, true);
|
||||||
|
|
||||||
|
// Destroy Foreign Toplevel
|
||||||
|
wlr_foreign_toplevel_handle_v1_destroy(PWINDOW->m_phForeignToplevel);
|
||||||
|
PWINDOW->m_phForeignToplevel = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Events::listener_commitWindow(void* owner, void* data) {
|
void Events::listener_commitWindow(void* owner, void* data) {
|
||||||
@@ -291,6 +363,9 @@ void Events::listener_setTitleWindow(void* owner, void* data) {
|
|||||||
if (PWINDOW == g_pCompositor->m_pLastWindow) // if it's the active, let's post an event to update others
|
if (PWINDOW == g_pCompositor->m_pLastWindow) // if it's the active, let's post an event to update others
|
||||||
g_pEventManager->postEvent(SHyprIPCEvent("activewindow", g_pXWaylandManager->getAppIDClass(PWINDOW) + "," + PWINDOW->m_szTitle));
|
g_pEventManager->postEvent(SHyprIPCEvent("activewindow", g_pXWaylandManager->getAppIDClass(PWINDOW) + "," + PWINDOW->m_szTitle));
|
||||||
|
|
||||||
|
if (PWINDOW->m_phForeignToplevel)
|
||||||
|
wlr_foreign_toplevel_handle_v1_set_title(PWINDOW->m_phForeignToplevel, PWINDOW->m_szTitle.c_str());
|
||||||
|
|
||||||
Debug::log(LOG, "Window %x set title to %s", PWINDOW, PWINDOW->m_szTitle.c_str());
|
Debug::log(LOG, "Window %x set title to %s", PWINDOW, PWINDOW->m_szTitle.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -301,9 +376,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);
|
g_pLayoutManager->getCurrentLayout()->fullscreenRequestForWindow(PWINDOW, FULLSCREEN_FULL);
|
||||||
} else {
|
} else {
|
||||||
g_pLayoutManager->getCurrentLayout()->fullscreenRequestForWindow(PWINDOW);
|
g_pLayoutManager->getCurrentLayout()->fullscreenRequestForWindow(PWINDOW, FULLSCREEN_FULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug::log(LOG, "Window %x fullscreen to %i", PWINDOW, PWINDOW->m_bIsFullscreen);
|
Debug::log(LOG, "Window %x fullscreen to %i", PWINDOW, PWINDOW->m_bIsFullscreen);
|
||||||
|
@@ -149,8 +149,6 @@ public:
|
|||||||
return false; // unreachable
|
return false; // unreachable
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
void warp() {
|
void warp() {
|
||||||
switch (m_eVarType) {
|
switch (m_eVarType) {
|
||||||
case AVARTYPE_FLOAT: {
|
case AVARTYPE_FLOAT: {
|
||||||
@@ -170,6 +168,8 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
Vector2D m_vValue = Vector2D(0,0);
|
Vector2D m_vValue = Vector2D(0,0);
|
||||||
float m_fValue = 0;
|
float m_fValue = 0;
|
||||||
CColor m_cValue;
|
CColor m_cValue;
|
||||||
|
@@ -46,16 +46,35 @@ void wlr_signal_emit_safe(struct wl_signal *signal, void *data) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::string getFormat(const char *fmt, ...) {
|
std::string getFormat(const char *fmt, ...) {
|
||||||
char buf[2048] = "";
|
char buf[LOGMESSAGESIZE] = "";
|
||||||
|
char* outputStr;
|
||||||
|
int logLen;
|
||||||
|
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, fmt);
|
va_start(args, fmt);
|
||||||
|
logLen = vsnprintf(buf, sizeof buf, fmt, args);
|
||||||
vsprintf(buf, fmt, args);
|
|
||||||
|
|
||||||
va_end(args);
|
va_end(args);
|
||||||
|
|
||||||
return std::string(buf);
|
if ((long unsigned int)logLen < sizeof buf) {
|
||||||
|
outputStr = strdup(buf);
|
||||||
|
} else {
|
||||||
|
outputStr = (char*)malloc(logLen + 1);
|
||||||
|
|
||||||
|
if (!outputStr) {
|
||||||
|
printf("CRITICAL: Cannot alloc size %d for log! (Out of memory?)", logLen + 1);
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
va_start(args, fmt);
|
||||||
|
vsnprintf(outputStr, logLen + 1U, fmt, args);
|
||||||
|
va_end(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string output = std::string(outputStr);
|
||||||
|
|
||||||
|
free(outputStr);
|
||||||
|
|
||||||
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
void scaleBox(wlr_box* box, float scale) {
|
void scaleBox(wlr_box* box, float scale) {
|
||||||
@@ -116,7 +135,7 @@ float getPlusMinusKeywordResult(std::string source, float relative) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool isNumber(const std::string& str) {
|
bool isNumber(const std::string& str) {
|
||||||
return std::ranges::all_of(str.begin(), str.end(), [](char c) { return isdigit(c) != 0; });
|
return std::ranges::all_of(str.begin(), str.end(), [](char c) { return isdigit(c) != 0 || c == '-'; });
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isDirection(const std::string& arg) {
|
bool isDirection(const std::string& arg) {
|
||||||
@@ -125,7 +144,10 @@ bool isDirection(const std::string& arg) {
|
|||||||
|
|
||||||
int getWorkspaceIDFromString(const std::string& in, std::string& outName) {
|
int getWorkspaceIDFromString(const std::string& in, std::string& outName) {
|
||||||
int result = INT_MAX;
|
int result = INT_MAX;
|
||||||
if (in.find("name:") == 0) {
|
if (in.find("special") == 0) {
|
||||||
|
outName = "special";
|
||||||
|
return SPECIAL_WORKSPACE_ID;
|
||||||
|
} else if (in.find("name:") == 0) {
|
||||||
const auto WORKSPACENAME = in.substr(in.find_first_of(':') + 1);
|
const auto WORKSPACENAME = in.substr(in.find_first_of(':') + 1);
|
||||||
const auto WORKSPACE = g_pCompositor->getWorkspaceByName(WORKSPACENAME);
|
const auto WORKSPACE = g_pCompositor->getWorkspaceByName(WORKSPACENAME);
|
||||||
if (!WORKSPACE) {
|
if (!WORKSPACE) {
|
||||||
@@ -135,8 +157,59 @@ int getWorkspaceIDFromString(const std::string& in, std::string& outName) {
|
|||||||
}
|
}
|
||||||
outName = WORKSPACENAME;
|
outName = WORKSPACENAME;
|
||||||
} else {
|
} else {
|
||||||
result = std::clamp((int)getPlusMinusKeywordResult(in, g_pCompositor->m_pLastMonitor->activeWorkspace), 1, INT_MAX);
|
if (in[0] == 'm') {
|
||||||
outName = std::to_string(result);
|
// monitor relative
|
||||||
|
result = (int)getPlusMinusKeywordResult(in.substr(1), 0);
|
||||||
|
|
||||||
|
// result now has +/- what we should move on mon
|
||||||
|
int remains = (int)result;
|
||||||
|
int currentID = g_pCompositor->m_pLastMonitor->activeWorkspace;
|
||||||
|
int searchID = currentID;
|
||||||
|
|
||||||
|
while (remains != 0) {
|
||||||
|
if (remains < 0)
|
||||||
|
searchID--;
|
||||||
|
else
|
||||||
|
searchID++;
|
||||||
|
|
||||||
|
if (g_pCompositor->workspaceIDOutOfBounds(searchID)){
|
||||||
|
// means we need to wrap around
|
||||||
|
int lowestID = 99999;
|
||||||
|
int highestID = -99999;
|
||||||
|
|
||||||
|
for (auto& w : g_pCompositor->m_lWorkspaces) {
|
||||||
|
if (w.m_iID < lowestID)
|
||||||
|
lowestID = w.m_iID;
|
||||||
|
|
||||||
|
if (w.m_iID > highestID)
|
||||||
|
highestID = w.m_iID;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (remains < 0)
|
||||||
|
searchID = highestID;
|
||||||
|
else
|
||||||
|
searchID = lowestID;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(searchID); PWORKSPACE && PWORKSPACE->m_iID != SPECIAL_WORKSPACE_ID) {
|
||||||
|
if (PWORKSPACE->m_iMonitorID == g_pCompositor->m_pLastMonitor->ID) {
|
||||||
|
currentID = PWORKSPACE->m_iID;
|
||||||
|
|
||||||
|
if (remains < 0)
|
||||||
|
remains++;
|
||||||
|
else
|
||||||
|
remains--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result = currentID;
|
||||||
|
outName = g_pCompositor->getWorkspaceByID(currentID)->m_szName;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
result = std::clamp((int)getPlusMinusKeywordResult(in, g_pCompositor->m_pLastMonitor->activeWorkspace), 1, INT_MAX);
|
||||||
|
outName = std::to_string(result);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@@ -7,9 +7,10 @@
|
|||||||
#include <array>
|
#include <array>
|
||||||
|
|
||||||
struct SMonitor {
|
struct SMonitor {
|
||||||
Vector2D vecPosition = Vector2D(0,0);
|
Vector2D vecPosition = Vector2D(0,0);
|
||||||
Vector2D vecSize = Vector2D(0,0);
|
Vector2D vecSize = Vector2D(0,0);
|
||||||
Vector2D vecPixelSize = Vector2D(0,0);
|
Vector2D vecPixelSize = Vector2D(0,0);
|
||||||
|
Vector2D vecTransformedSize = Vector2D(0,0);
|
||||||
|
|
||||||
bool primary = false;
|
bool primary = false;
|
||||||
|
|
||||||
@@ -26,7 +27,12 @@ struct SMonitor {
|
|||||||
wlr_output* output = nullptr;
|
wlr_output* output = nullptr;
|
||||||
float refreshRate = 60;
|
float refreshRate = 60;
|
||||||
wlr_output_damage* damage = nullptr;
|
wlr_output_damage* damage = nullptr;
|
||||||
bool needsFrameSkip = false;
|
int framesToSkip = 0;
|
||||||
|
bool noFrameSchedule = false;
|
||||||
|
wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
||||||
|
|
||||||
|
// for the special workspace
|
||||||
|
bool specialWorkspaceOpen = false;
|
||||||
|
|
||||||
// Double-linked list because we need to have constant mem addresses for signals
|
// Double-linked list because we need to have constant mem addresses for signals
|
||||||
// We have to store pointers and use raw new/delete because they might be moved between them
|
// We have to store pointers and use raw new/delete because they might be moved between them
|
||||||
|
@@ -20,12 +20,13 @@ void addSurfaceGlobalOffset(SSurfaceTreeNode* node, int* lx, int* ly) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SSurfaceTreeNode* createTree(wlr_surface* pSurface) {
|
SSurfaceTreeNode* createTree(wlr_surface* pSurface, CWindow* pWindow) {
|
||||||
SubsurfaceTree::surfaceTreeNodes.push_back(SSurfaceTreeNode());
|
SubsurfaceTree::surfaceTreeNodes.push_back(SSurfaceTreeNode());
|
||||||
|
|
||||||
const auto PNODE = &SubsurfaceTree::surfaceTreeNodes.back();
|
const auto PNODE = &SubsurfaceTree::surfaceTreeNodes.back();
|
||||||
|
|
||||||
PNODE->pSurface = pSurface;
|
PNODE->pSurface = pSurface;
|
||||||
|
PNODE->pWindowOwner = pWindow;
|
||||||
|
|
||||||
PNODE->hyprListener_newSubsurface.initCallback(&pSurface->events.new_subsurface, &Events::listener_newSubsurfaceNode, PNODE, "SurfaceTreeNode");
|
PNODE->hyprListener_newSubsurface.initCallback(&pSurface->events.new_subsurface, &Events::listener_newSubsurfaceNode, PNODE, "SurfaceTreeNode");
|
||||||
PNODE->hyprListener_commit.initCallback(&pSurface->events.commit, &Events::listener_commitSubsurface, PNODE, "SurfaceTreeNode");
|
PNODE->hyprListener_commit.initCallback(&pSurface->events.commit, &Events::listener_commitSubsurface, PNODE, "SurfaceTreeNode");
|
||||||
@@ -42,16 +43,21 @@ SSurfaceTreeNode* createTree(wlr_surface* pSurface) {
|
|||||||
return PNODE;
|
return PNODE;
|
||||||
}
|
}
|
||||||
|
|
||||||
SSurfaceTreeNode* createSubsurfaceNode(SSurfaceTreeNode* pParent, SSubsurface* pSubsurface, wlr_surface* surface) {
|
SSurfaceTreeNode* createSubsurfaceNode(SSurfaceTreeNode* pParent, SSubsurface* pSubsurface, wlr_surface* surface, CWindow* pWindow) {
|
||||||
const auto PNODE = createTree(surface);
|
const auto PNODE = createTree(surface, pWindow);
|
||||||
PNODE->pParent = pParent;
|
PNODE->pParent = pParent;
|
||||||
PNODE->pSubsurface = pSubsurface;
|
PNODE->pSubsurface = pSubsurface;
|
||||||
|
|
||||||
|
Debug::log(LOG, "Creating a subsurface Node! (pWindow: %x)", pWindow);
|
||||||
|
|
||||||
return PNODE;
|
return PNODE;
|
||||||
}
|
}
|
||||||
|
|
||||||
SSurfaceTreeNode* SubsurfaceTree::createTreeRoot(wlr_surface* pSurface, applyGlobalOffsetFn fn, void* data) {
|
SSurfaceTreeNode* SubsurfaceTree::createTreeRoot(wlr_surface* pSurface, applyGlobalOffsetFn fn, void* data, CWindow* pWindow) {
|
||||||
const auto PNODE = createTree(pSurface);
|
const auto PNODE = createTree(pSurface, pWindow);
|
||||||
|
|
||||||
|
Debug::log(LOG, "Creating a surfaceTree Root! (pWindow: %x)", pWindow);
|
||||||
|
|
||||||
PNODE->offsetfn = fn;
|
PNODE->offsetfn = fn;
|
||||||
PNODE->globalOffsetData = data;
|
PNODE->globalOffsetData = data;
|
||||||
|
|
||||||
@@ -83,6 +89,20 @@ void SubsurfaceTree::destroySurfaceTree(SSurfaceTreeNode* pNode) {
|
|||||||
pNode->hyprListener_destroy.removeCallback();
|
pNode->hyprListener_destroy.removeCallback();
|
||||||
pNode->hyprListener_newSubsurface.removeCallback();
|
pNode->hyprListener_newSubsurface.removeCallback();
|
||||||
|
|
||||||
|
// damage
|
||||||
|
if (pNode->pSurface) {
|
||||||
|
wlr_box extents = {};
|
||||||
|
wlr_surface_get_extends(pNode->pSurface, &extents);
|
||||||
|
|
||||||
|
int lx = 0, ly = 0;
|
||||||
|
addSurfaceGlobalOffset(pNode, &lx, &ly);
|
||||||
|
|
||||||
|
extents.x += lx;
|
||||||
|
extents.y += ly;
|
||||||
|
|
||||||
|
g_pHyprRenderer->damageBox(&extents);
|
||||||
|
}
|
||||||
|
|
||||||
surfaceTreeNodes.remove(*pNode);
|
surfaceTreeNodes.remove(*pNode);
|
||||||
|
|
||||||
Debug::log(LOG, "SurfaceTree Node removed");
|
Debug::log(LOG, "SurfaceTree Node removed");
|
||||||
@@ -120,6 +140,8 @@ void Events::listener_newSubsurfaceNode(void* owner, void* data) {
|
|||||||
PNEWSUBSURFACE->hyprListener_unmap.initCallback(&PSUBSURFACE->events.unmap, &Events::listener_unmapSubsurface, PNEWSUBSURFACE, "Subsurface");
|
PNEWSUBSURFACE->hyprListener_unmap.initCallback(&PSUBSURFACE->events.unmap, &Events::listener_unmapSubsurface, PNEWSUBSURFACE, "Subsurface");
|
||||||
PNEWSUBSURFACE->hyprListener_destroy.initCallback(&PSUBSURFACE->events.destroy, &Events::listener_destroySubsurface, PNEWSUBSURFACE, "Subsurface");
|
PNEWSUBSURFACE->hyprListener_destroy.initCallback(&PSUBSURFACE->events.destroy, &Events::listener_destroySubsurface, PNEWSUBSURFACE, "Subsurface");
|
||||||
|
|
||||||
|
PNEWSUBSURFACE->pWindowOwner = pNode->pWindowOwner;
|
||||||
|
|
||||||
wlr_subsurface* existingWlrSubsurface;
|
wlr_subsurface* existingWlrSubsurface;
|
||||||
wl_list_for_each(existingWlrSubsurface, &PSUBSURFACE->surface->current.subsurfaces_below, current.link) {
|
wl_list_for_each(existingWlrSubsurface, &PSUBSURFACE->surface->current.subsurfaces_below, current.link) {
|
||||||
listener_newSubsurfaceNode(pNode, existingWlrSubsurface);
|
listener_newSubsurfaceNode(pNode, existingWlrSubsurface);
|
||||||
@@ -134,7 +156,7 @@ void Events::listener_mapSubsurface(void* owner, void* data) {
|
|||||||
|
|
||||||
Debug::log(LOG, "Subsurface %x mapped", subsurface->pSubsurface);
|
Debug::log(LOG, "Subsurface %x mapped", subsurface->pSubsurface);
|
||||||
|
|
||||||
subsurface->pChild = createSubsurfaceNode(subsurface->pParent, subsurface, subsurface->pSubsurface->surface);
|
subsurface->pChild = createSubsurfaceNode(subsurface->pParent, subsurface, subsurface->pSubsurface->surface, subsurface->pWindowOwner);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Events::listener_unmapSubsurface(void* owner, void* data) {
|
void Events::listener_unmapSubsurface(void* owner, void* data) {
|
||||||
@@ -154,6 +176,8 @@ void Events::listener_unmapSubsurface(void* owner, void* data) {
|
|||||||
extents.x += lx;
|
extents.x += lx;
|
||||||
extents.y += ly;
|
extents.y += ly;
|
||||||
|
|
||||||
|
g_pHyprRenderer->damageBox(&extents);
|
||||||
|
|
||||||
SubsurfaceTree::destroySurfaceTree(subsurface->pChild);
|
SubsurfaceTree::destroySurfaceTree(subsurface->pChild);
|
||||||
subsurface->pChild = nullptr;
|
subsurface->pChild = nullptr;
|
||||||
}
|
}
|
||||||
@@ -162,6 +186,14 @@ void Events::listener_unmapSubsurface(void* owner, void* data) {
|
|||||||
void Events::listener_commitSubsurface(void* owner, void* data) {
|
void Events::listener_commitSubsurface(void* owner, void* data) {
|
||||||
SSurfaceTreeNode* pNode = (SSurfaceTreeNode*)owner;
|
SSurfaceTreeNode* pNode = (SSurfaceTreeNode*)owner;
|
||||||
|
|
||||||
|
// no damaging if it's not visible
|
||||||
|
if (!g_pHyprRenderer->shouldRenderWindow(pNode->pWindowOwner)) {
|
||||||
|
if (g_pConfigManager->getInt("debug:log_damage"))
|
||||||
|
Debug::log(LOG, "Refusing to commit damage from %x because it's invisible.", pNode->pWindowOwner);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int lx = 0, ly = 0;
|
int lx = 0, ly = 0;
|
||||||
|
|
||||||
addSurfaceGlobalOffset(pNode, &lx, &ly);
|
addSurfaceGlobalOffset(pNode, &lx, &ly);
|
||||||
|
@@ -4,6 +4,7 @@
|
|||||||
#include <list>
|
#include <list>
|
||||||
|
|
||||||
struct SSubsurface;
|
struct SSubsurface;
|
||||||
|
class CWindow;
|
||||||
|
|
||||||
typedef void (*applyGlobalOffsetFn)(void *, int *, int *);
|
typedef void (*applyGlobalOffsetFn)(void *, int *, int *);
|
||||||
|
|
||||||
@@ -21,6 +22,7 @@ struct SSurfaceTreeNode {
|
|||||||
|
|
||||||
applyGlobalOffsetFn offsetfn;
|
applyGlobalOffsetFn offsetfn;
|
||||||
void *globalOffsetData;
|
void *globalOffsetData;
|
||||||
|
CWindow* pWindowOwner = nullptr;
|
||||||
|
|
||||||
bool operator==(const SSurfaceTreeNode& rhs) {
|
bool operator==(const SSurfaceTreeNode& rhs) {
|
||||||
return pSurface == rhs.pSurface;
|
return pSurface == rhs.pSurface;
|
||||||
@@ -37,13 +39,15 @@ struct SSubsurface {
|
|||||||
DYNLISTENER(unmap);
|
DYNLISTENER(unmap);
|
||||||
DYNLISTENER(destroy);
|
DYNLISTENER(destroy);
|
||||||
|
|
||||||
|
CWindow* pWindowOwner = nullptr;
|
||||||
|
|
||||||
bool operator==(const SSubsurface& rhs) {
|
bool operator==(const SSubsurface& rhs) {
|
||||||
return pSubsurface == rhs.pSubsurface;
|
return pSubsurface == rhs.pSubsurface;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace SubsurfaceTree {
|
namespace SubsurfaceTree {
|
||||||
SSurfaceTreeNode* createTreeRoot(wlr_surface*, applyGlobalOffsetFn, void*);
|
SSurfaceTreeNode* createTreeRoot(wlr_surface*, applyGlobalOffsetFn, void*, CWindow* pWindow = nullptr);
|
||||||
void destroySurfaceTree(SSurfaceTreeNode*);
|
void destroySurfaceTree(SSurfaceTreeNode*);
|
||||||
|
|
||||||
inline std::list<SSurfaceTreeNode> surfaceTreeNodes;
|
inline std::list<SSurfaceTreeNode> surfaceTreeNodes;
|
||||||
|
@@ -57,6 +57,9 @@ struct SRenderData {
|
|||||||
|
|
||||||
// for decorations (border)
|
// for decorations (border)
|
||||||
bool decorate = false;
|
bool decorate = false;
|
||||||
|
|
||||||
|
// for custom round values
|
||||||
|
int rounding = -1; // -1 means not set
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SKeyboard {
|
struct SKeyboard {
|
||||||
@@ -66,6 +69,8 @@ struct SKeyboard {
|
|||||||
DYNLISTENER(keyboardKey);
|
DYNLISTENER(keyboardKey);
|
||||||
DYNLISTENER(keyboardDestroy);
|
DYNLISTENER(keyboardDestroy);
|
||||||
|
|
||||||
|
bool active = false;
|
||||||
|
|
||||||
// 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;
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
#include "Workspace.hpp"
|
#include "Workspace.hpp"
|
||||||
#include "../Compositor.hpp"
|
#include "../Compositor.hpp"
|
||||||
|
|
||||||
CWorkspace::CWorkspace(int monitorID) {
|
CWorkspace::CWorkspace(int monitorID, bool special) {
|
||||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(monitorID);
|
const auto PMONITOR = g_pCompositor->getMonitorFromID(monitorID);
|
||||||
|
|
||||||
if (!PMONITOR) {
|
if (!PMONITOR) {
|
||||||
@@ -10,16 +10,20 @@ CWorkspace::CWorkspace(int monitorID) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_iMonitorID = monitorID;
|
m_iMonitorID = monitorID;
|
||||||
|
|
||||||
m_pWlrHandle = wlr_ext_workspace_handle_v1_create(PMONITOR->pWLRWorkspaceGroupHandle);
|
|
||||||
|
|
||||||
// set geometry here cuz we can
|
m_bIsSpecialWorkspace = special;
|
||||||
wl_array_init(&m_wlrCoordinateArr);
|
|
||||||
*reinterpret_cast<int*>(wl_array_add(&m_wlrCoordinateArr, sizeof(int))) = (int)PMONITOR->vecPosition.x;
|
if (!special) {
|
||||||
*reinterpret_cast<int*>(wl_array_add(&m_wlrCoordinateArr, sizeof(int))) = (int)PMONITOR->vecPosition.y;
|
m_pWlrHandle = wlr_ext_workspace_handle_v1_create(PMONITOR->pWLRWorkspaceGroupHandle);
|
||||||
wlr_ext_workspace_handle_v1_set_coordinates(m_pWlrHandle, &m_wlrCoordinateArr);
|
|
||||||
wlr_ext_workspace_handle_v1_set_hidden(m_pWlrHandle, false);
|
// set geometry here cuz we can
|
||||||
wlr_ext_workspace_handle_v1_set_urgent(m_pWlrHandle, false);
|
wl_array_init(&m_wlrCoordinateArr);
|
||||||
|
*reinterpret_cast<int*>(wl_array_add(&m_wlrCoordinateArr, sizeof(int))) = (int)PMONITOR->vecPosition.x;
|
||||||
|
*reinterpret_cast<int*>(wl_array_add(&m_wlrCoordinateArr, sizeof(int))) = (int)PMONITOR->vecPosition.y;
|
||||||
|
wlr_ext_workspace_handle_v1_set_coordinates(m_pWlrHandle, &m_wlrCoordinateArr);
|
||||||
|
wlr_ext_workspace_handle_v1_set_hidden(m_pWlrHandle, false);
|
||||||
|
wlr_ext_workspace_handle_v1_set_urgent(m_pWlrHandle, false);
|
||||||
|
}
|
||||||
|
|
||||||
m_vRenderOffset.m_pWorkspace = this;
|
m_vRenderOffset.m_pWorkspace = this;
|
||||||
m_vRenderOffset.create(AVARTYPE_VECTOR, &g_pConfigManager->getConfigValuePtr("animations:workspaces_speed")->floatValue, &g_pConfigManager->getConfigValuePtr("animations:workspaces")->intValue, &g_pConfigManager->getConfigValuePtr("animations:workspaces_curve")->strValue, nullptr, AVARDAMAGE_ENTIRE);
|
m_vRenderOffset.create(AVARTYPE_VECTOR, &g_pConfigManager->getConfigValuePtr("animations:workspaces_speed")->floatValue, &g_pConfigManager->getConfigValuePtr("animations:workspaces")->intValue, &g_pConfigManager->getConfigValuePtr("animations:workspaces_curve")->strValue, nullptr, AVARDAMAGE_ENTIRE);
|
||||||
@@ -31,6 +35,8 @@ CWorkspace::CWorkspace(int monitorID) {
|
|||||||
CWorkspace::~CWorkspace() {
|
CWorkspace::~CWorkspace() {
|
||||||
m_vRenderOffset.unregister();
|
m_vRenderOffset.unregister();
|
||||||
|
|
||||||
|
Debug::log(LOG, "Destroying workspace ID %d", m_iID);
|
||||||
|
|
||||||
if (m_pWlrHandle) {
|
if (m_pWlrHandle) {
|
||||||
wlr_ext_workspace_handle_v1_set_active(m_pWlrHandle, false);
|
wlr_ext_workspace_handle_v1_set_active(m_pWlrHandle, false);
|
||||||
wlr_ext_workspace_handle_v1_destroy(m_pWlrHandle);
|
wlr_ext_workspace_handle_v1_destroy(m_pWlrHandle);
|
||||||
@@ -38,7 +44,7 @@ CWorkspace::~CWorkspace() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CWorkspace::startAnim(bool in, bool left) {
|
void CWorkspace::startAnim(bool in, bool left, bool instant) {
|
||||||
const auto ANIMSTYLE = g_pConfigManager->getString("animations:workspaces_style");
|
const auto ANIMSTYLE = g_pConfigManager->getString("animations:workspaces_style");
|
||||||
|
|
||||||
if (ANIMSTYLE == "fade") {
|
if (ANIMSTYLE == "fade") {
|
||||||
@@ -51,6 +57,18 @@ void CWorkspace::startAnim(bool in, bool left) {
|
|||||||
m_fAlpha.setValueAndWarp(255.f);
|
m_fAlpha.setValueAndWarp(255.f);
|
||||||
m_fAlpha = 0.f;
|
m_fAlpha = 0.f;
|
||||||
}
|
}
|
||||||
|
} else if (ANIMSTYLE == "slidevert") {
|
||||||
|
// fallback is slide
|
||||||
|
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
|
||||||
|
|
||||||
|
m_fAlpha.setValueAndWarp(255.f); // fix a bug, if switching from fade -> slide.
|
||||||
|
|
||||||
|
if (in) {
|
||||||
|
m_vRenderOffset.setValueAndWarp(Vector2D(0, left ? PMONITOR->vecSize.y : -PMONITOR->vecSize.y));
|
||||||
|
m_vRenderOffset = Vector2D(0, 0);
|
||||||
|
} else {
|
||||||
|
m_vRenderOffset = Vector2D(0, left ? -PMONITOR->vecSize.y : PMONITOR->vecSize.y);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// fallback is slide
|
// fallback is slide
|
||||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
|
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
|
||||||
@@ -64,10 +82,37 @@ void CWorkspace::startAnim(bool in, bool left) {
|
|||||||
m_vRenderOffset = Vector2D(left ? -PMONITOR->vecSize.x : PMONITOR->vecSize.x, 0);
|
m_vRenderOffset = Vector2D(left ? -PMONITOR->vecSize.x : PMONITOR->vecSize.x, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (instant) {
|
||||||
|
m_vRenderOffset.warp();
|
||||||
|
m_fAlpha.warp();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CWorkspace::setActive(bool on) {
|
void CWorkspace::setActive(bool on) {
|
||||||
if (m_pWlrHandle) {
|
if (m_pWlrHandle) {
|
||||||
wlr_ext_workspace_handle_v1_set_active(m_pWlrHandle, on);
|
wlr_ext_workspace_handle_v1_set_active(m_pWlrHandle, on);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CWorkspace::moveToMonitor(const int& id) {
|
||||||
|
const auto PMONITOR = g_pCompositor->getMonitorFromID(id);
|
||||||
|
|
||||||
|
if (!PMONITOR || m_bIsSpecialWorkspace)
|
||||||
|
return;
|
||||||
|
|
||||||
|
wlr_ext_workspace_handle_v1_set_active(m_pWlrHandle, false);
|
||||||
|
wlr_ext_workspace_handle_v1_destroy(m_pWlrHandle);
|
||||||
|
|
||||||
|
m_pWlrHandle = wlr_ext_workspace_handle_v1_create(PMONITOR->pWLRWorkspaceGroupHandle);
|
||||||
|
|
||||||
|
// set geometry here cuz we can
|
||||||
|
wl_array_init(&m_wlrCoordinateArr);
|
||||||
|
*reinterpret_cast<int*>(wl_array_add(&m_wlrCoordinateArr, sizeof(int))) = (int)PMONITOR->vecPosition.x;
|
||||||
|
*reinterpret_cast<int*>(wl_array_add(&m_wlrCoordinateArr, sizeof(int))) = (int)PMONITOR->vecPosition.y;
|
||||||
|
wlr_ext_workspace_handle_v1_set_coordinates(m_pWlrHandle, &m_wlrCoordinateArr);
|
||||||
|
wlr_ext_workspace_handle_v1_set_hidden(m_pWlrHandle, false);
|
||||||
|
wlr_ext_workspace_handle_v1_set_urgent(m_pWlrHandle, false);
|
||||||
|
|
||||||
|
wlr_ext_workspace_handle_v1_set_name(m_pWlrHandle, m_szName.c_str());
|
||||||
}
|
}
|
@@ -3,9 +3,14 @@
|
|||||||
#include "../defines.hpp"
|
#include "../defines.hpp"
|
||||||
#include "AnimatedVariable.hpp"
|
#include "AnimatedVariable.hpp"
|
||||||
|
|
||||||
|
enum eFullscreenMode : uint8_t {
|
||||||
|
FULLSCREEN_FULL = 0,
|
||||||
|
FULLSCREEN_MAXIMIZED
|
||||||
|
};
|
||||||
|
|
||||||
class CWorkspace {
|
class CWorkspace {
|
||||||
public:
|
public:
|
||||||
CWorkspace(int monitorID);
|
CWorkspace(int monitorID, bool special = false);
|
||||||
~CWorkspace();
|
~CWorkspace();
|
||||||
|
|
||||||
// Workspaces ID-based have IDs > 0
|
// Workspaces ID-based have IDs > 0
|
||||||
@@ -14,6 +19,7 @@ public:
|
|||||||
std::string m_szName = "";
|
std::string m_szName = "";
|
||||||
uint64_t m_iMonitorID = -1;
|
uint64_t m_iMonitorID = -1;
|
||||||
bool m_bHasFullscreenWindow = false;
|
bool m_bHasFullscreenWindow = false;
|
||||||
|
eFullscreenMode m_efFullscreenMode = FULLSCREEN_FULL;
|
||||||
|
|
||||||
wlr_ext_workspace_handle_v1* m_pWlrHandle = nullptr;
|
wlr_ext_workspace_handle_v1* m_pWlrHandle = nullptr;
|
||||||
|
|
||||||
@@ -23,10 +29,15 @@ public:
|
|||||||
CAnimatedVariable m_vRenderOffset;
|
CAnimatedVariable m_vRenderOffset;
|
||||||
CAnimatedVariable m_fAlpha;
|
CAnimatedVariable m_fAlpha;
|
||||||
|
|
||||||
|
// "scratchpad"
|
||||||
|
bool m_bIsSpecialWorkspace = false;
|
||||||
|
|
||||||
// user-set
|
// user-set
|
||||||
bool m_bDefaultFloating = false;
|
bool m_bDefaultFloating = false;
|
||||||
bool m_bDefaultPseudo = false;
|
bool m_bDefaultPseudo = false;
|
||||||
|
|
||||||
void startAnim(bool in, bool left);
|
void startAnim(bool in, bool left, bool instant = false);
|
||||||
void setActive(bool on);
|
void setActive(bool on);
|
||||||
|
|
||||||
|
void moveToMonitor(const int&);
|
||||||
};
|
};
|
@@ -34,55 +34,56 @@
|
|||||||
#define static
|
#define static
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include <wlr/backend.h>
|
#include "../wlroots/include/wlr/backend.h"
|
||||||
#include <wlr/backend/libinput.h>
|
#include "../wlroots/include/wlr/backend/libinput.h"
|
||||||
#include <wlr/render/allocator.h>
|
#include "../wlroots/include/wlr/render/allocator.h"
|
||||||
#include <wlr/render/wlr_renderer.h>
|
#include "../wlroots/include/wlr/render/wlr_renderer.h"
|
||||||
#include <wlr/types/wlr_compositor.h>
|
#include "../wlroots/include/wlr/types/wlr_compositor.h"
|
||||||
#include <wlr/types/wlr_cursor.h>
|
#include "../wlroots/include/wlr/types/wlr_cursor.h"
|
||||||
#include <wlr/types/wlr_data_control_v1.h>
|
#include "../wlroots/include/wlr/types/wlr_data_control_v1.h"
|
||||||
#include <wlr/types/wlr_data_device.h>
|
#include "../wlroots/include/wlr/types/wlr_data_device.h"
|
||||||
#include <wlr/types/wlr_export_dmabuf_v1.h>
|
#include "../wlroots/include/wlr/types/wlr_export_dmabuf_v1.h"
|
||||||
#include <wlr/types/wlr_linux_dmabuf_v1.h>
|
#include "../wlroots/include/wlr/types/wlr_linux_dmabuf_v1.h"
|
||||||
#include <wlr/types/wlr_gamma_control_v1.h>
|
#include "../wlroots/include/wlr/types/wlr_gamma_control_v1.h"
|
||||||
#include <wlr/types/wlr_idle.h>
|
#include "../wlroots/include/wlr/types/wlr_idle.h"
|
||||||
#include <wlr/types/wlr_input_device.h>
|
#include "../wlroots/include/wlr/types/wlr_input_device.h"
|
||||||
#include <wlr/types/wlr_keyboard.h>
|
#include "../wlroots/include/wlr/types/wlr_keyboard.h"
|
||||||
#include <wlr/types/wlr_layer_shell_v1.h>
|
#include "../wlroots/include/wlr/types/wlr_layer_shell_v1.h"
|
||||||
#include <wlr/types/wlr_matrix.h>
|
#include "../wlroots/include/wlr/types/wlr_matrix.h"
|
||||||
#include <wlr/types/wlr_output.h>
|
#include "../wlroots/include/wlr/types/wlr_output.h"
|
||||||
#include <wlr/types/wlr_output_layout.h>
|
#include "../wlroots/include/wlr/types/wlr_output_layout.h"
|
||||||
#include <wlr/types/wlr_output_management_v1.h>
|
#include "../wlroots/include/wlr/types/wlr_output_management_v1.h"
|
||||||
#include <wlr/types/wlr_pointer.h>
|
#include "../wlroots/include/wlr/types/wlr_pointer.h"
|
||||||
#include <wlr/types/wlr_presentation_time.h>
|
#include "../wlroots/include/wlr/types/wlr_presentation_time.h"
|
||||||
#include <wlr/types/wlr_primary_selection.h>
|
#include "../wlroots/include/wlr/types/wlr_primary_selection.h"
|
||||||
#include <wlr/types/wlr_primary_selection_v1.h>
|
#include "../wlroots/include/wlr/types/wlr_primary_selection_v1.h"
|
||||||
#include <wlr/types/wlr_screencopy_v1.h>
|
#include "../wlroots/include/wlr/types/wlr_screencopy_v1.h"
|
||||||
#include <wlr/types/wlr_seat.h>
|
#include "../wlroots/include/wlr/types/wlr_seat.h"
|
||||||
#include <wlr/types/wlr_server_decoration.h>
|
#include "../wlroots/include/wlr/types/wlr_server_decoration.h"
|
||||||
#include <wlr/types/wlr_viewporter.h>
|
#include "../wlroots/include/wlr/types/wlr_viewporter.h"
|
||||||
#include <wlr/types/wlr_virtual_keyboard_v1.h>
|
#include "../wlroots/include/wlr/types/wlr_virtual_keyboard_v1.h"
|
||||||
#include <wlr/types/wlr_xcursor_manager.h>
|
#include "../wlroots/include/wlr/types/wlr_xcursor_manager.h"
|
||||||
#include <wlr/types/wlr_xdg_activation_v1.h>
|
#include "../wlroots/include/wlr/types/wlr_xdg_activation_v1.h"
|
||||||
#include <wlr/types/wlr_xdg_decoration_v1.h>
|
#include "../wlroots/include/wlr/types/wlr_xdg_decoration_v1.h"
|
||||||
#include <wlr/types/wlr_xdg_output_v1.h>
|
#include "../wlroots/include/wlr/types/wlr_xdg_output_v1.h"
|
||||||
#include <wlr/types/wlr_xdg_shell.h>
|
#include "../wlroots/include/wlr/types/wlr_xdg_shell.h"
|
||||||
#include <wlr/types/wlr_subcompositor.h>
|
#include "../wlroots/include/wlr/types/wlr_subcompositor.h"
|
||||||
#include <wlr/types/wlr_scene.h>
|
#include "../wlroots/include/wlr/types/wlr_scene.h"
|
||||||
#include <wlr/types/wlr_output_damage.h>
|
#include "../wlroots/include/wlr/types/wlr_output_damage.h"
|
||||||
#include <wlr/types/wlr_input_inhibitor.h>
|
#include "../wlroots/include/wlr/types/wlr_input_inhibitor.h"
|
||||||
#include <wlr/types/wlr_keyboard_shortcuts_inhibit_v1.h>
|
#include "../wlroots/include/wlr/types/wlr_keyboard_shortcuts_inhibit_v1.h"
|
||||||
#include <wlr/types/wlr_virtual_pointer_v1.h>
|
#include "../wlroots/include/wlr/types/wlr_virtual_pointer_v1.h"
|
||||||
#include <wlr/util/log.h>
|
#include "../wlroots/include/wlr/types/wlr_foreign_toplevel_management_v1.h"
|
||||||
#include <wlr/xwayland.h>
|
#include "../wlroots/include/wlr/util/log.h"
|
||||||
#include <wlr/util/region.h>
|
#include "../wlroots/include/wlr/xwayland.h"
|
||||||
|
#include "../wlroots/include/wlr/util/region.h"
|
||||||
#include <xkbcommon/xkbcommon.h>
|
#include <xkbcommon/xkbcommon.h>
|
||||||
#include <X11/Xproto.h>
|
#include <X11/Xproto.h>
|
||||||
#include <wlr/render/egl.h>
|
#include "../wlroots/include/wlr/render/egl.h"
|
||||||
#include <wlr/render/gles2.h>
|
#include "../wlroots/include/wlr/render/gles2.h"
|
||||||
#include <wlr/render/wlr_texture.h>
|
#include "../wlroots/include/wlr/render/wlr_texture.h"
|
||||||
#include <wlr/types/wlr_pointer_constraints_v1.h>
|
#include "../wlroots/include/wlr/types/wlr_pointer_constraints_v1.h"
|
||||||
#include <wlr/types/wlr_relative_pointer_v1.h>
|
#include "../wlroots/include/wlr/types/wlr_relative_pointer_v1.h"
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef class
|
#undef class
|
||||||
|
@@ -160,10 +160,22 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PWINDOW->m_vRealSize = calcSize;
|
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(PWINDOW->m_iWorkspaceID);
|
||||||
PWINDOW->m_vRealPosition = calcPos;
|
|
||||||
|
|
||||||
g_pXWaylandManager->setWindowSize(PWINDOW, calcSize);
|
if (PWORKSPACE->m_bIsSpecialWorkspace) {
|
||||||
|
// if special, we adjust the coords a bit
|
||||||
|
static auto *const PSCALEFACTOR = &g_pConfigManager->getConfigValuePtr("dwindle:special_scale_factor")->floatValue;
|
||||||
|
|
||||||
|
PWINDOW->m_vRealPosition = calcPos + (calcSize - calcSize * *PSCALEFACTOR) / 2.f;
|
||||||
|
PWINDOW->m_vRealSize = calcSize * *PSCALEFACTOR;
|
||||||
|
|
||||||
|
g_pXWaylandManager->setWindowSize(PWINDOW, calcSize * *PSCALEFACTOR);
|
||||||
|
} else {
|
||||||
|
PWINDOW->m_vRealSize = calcSize;
|
||||||
|
PWINDOW->m_vRealPosition = calcPos;
|
||||||
|
|
||||||
|
g_pXWaylandManager->setWindowSize(PWINDOW, calcSize);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CHyprDwindleLayout::onWindowCreated(CWindow* pWindow) {
|
void CHyprDwindleLayout::onWindowCreated(CWindow* pWindow) {
|
||||||
@@ -184,7 +196,7 @@ void CHyprDwindleLayout::onWindowCreated(CWindow* pWindow) {
|
|||||||
SDwindleNodeData* OPENINGON;
|
SDwindleNodeData* OPENINGON;
|
||||||
const auto MONFROMCURSOR = g_pCompositor->getMonitorFromCursor();
|
const auto MONFROMCURSOR = g_pCompositor->getMonitorFromCursor();
|
||||||
|
|
||||||
if (PMONITOR->ID == MONFROMCURSOR->ID && PNODE->workspaceID == PMONITOR->activeWorkspace) {
|
if (PMONITOR->ID == MONFROMCURSOR->ID && (PNODE->workspaceID == PMONITOR->activeWorkspace || (PNODE->workspaceID == SPECIAL_WORKSPACE_ID && PMONITOR->specialWorkspaceOpen))) {
|
||||||
OPENINGON = getNodeFromWindow(g_pCompositor->vectorToWindowTiled(g_pInputManager->getMouseCoordsInternal()));
|
OPENINGON = getNodeFromWindow(g_pCompositor->vectorToWindowTiled(g_pInputManager->getMouseCoordsInternal()));
|
||||||
|
|
||||||
// happens on reserved area
|
// happens on reserved area
|
||||||
@@ -196,6 +208,11 @@ void CHyprDwindleLayout::onWindowCreated(CWindow* pWindow) {
|
|||||||
|
|
||||||
Debug::log(LOG, "OPENINGON: %x, Workspace: %i, Monitor: %i", OPENINGON, PNODE->workspaceID, PMONITOR->ID);
|
Debug::log(LOG, "OPENINGON: %x, Workspace: %i, Monitor: %i", OPENINGON, PNODE->workspaceID, PMONITOR->ID);
|
||||||
|
|
||||||
|
if (OPENINGON && OPENINGON->workspaceID != PNODE->workspaceID) {
|
||||||
|
// special workspace handling
|
||||||
|
OPENINGON = getFirstNodeOnWorkspace(PNODE->workspaceID);
|
||||||
|
}
|
||||||
|
|
||||||
// if it's the first, it's easy. Make it fullscreen.
|
// if it's the first, it's easy. Make it fullscreen.
|
||||||
if (!OPENINGON || OPENINGON->pWindow == pWindow) {
|
if (!OPENINGON || OPENINGON->pWindow == pWindow) {
|
||||||
PNODE->position = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft;
|
PNODE->position = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft;
|
||||||
@@ -275,6 +292,10 @@ void CHyprDwindleLayout::onWindowCreated(CWindow* pWindow) {
|
|||||||
|
|
||||||
if (OPENINGON->pGroupParent) {
|
if (OPENINGON->pGroupParent) {
|
||||||
// means we opened on a group
|
// means we opened on a group
|
||||||
|
|
||||||
|
// add the group deco
|
||||||
|
pWindow->m_dWindowDecorations.emplace_back(std::make_unique<CHyprGroupBarDecoration>(pWindow));
|
||||||
|
|
||||||
PNODE->pGroupParent = OPENINGON->pGroupParent;
|
PNODE->pGroupParent = OPENINGON->pGroupParent;
|
||||||
PNODE->pGroupParent->groupMembers.push_back(PNODE);
|
PNODE->pGroupParent->groupMembers.push_back(PNODE);
|
||||||
PNODE->pGroupParent->groupMemberActive = PNODE->pGroupParent->groupMembers.size() - 1;
|
PNODE->pGroupParent->groupMemberActive = PNODE->pGroupParent->groupMembers.size() - 1;
|
||||||
@@ -352,6 +373,19 @@ void CHyprDwindleLayout::recalculateMonitor(const int& monid) {
|
|||||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(monid);
|
const auto PMONITOR = g_pCompositor->getMonitorFromID(monid);
|
||||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(PMONITOR->activeWorkspace);
|
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(PMONITOR->activeWorkspace);
|
||||||
|
|
||||||
|
if (!PWORKSPACE)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (PMONITOR->specialWorkspaceOpen) {
|
||||||
|
const auto TOPNODE = getMasterNodeOnWorkspace(SPECIAL_WORKSPACE_ID);
|
||||||
|
|
||||||
|
if (TOPNODE && PMONITOR) {
|
||||||
|
TOPNODE->position = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft;
|
||||||
|
TOPNODE->size = PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight;
|
||||||
|
TOPNODE->recalcSizePosRecursive();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Ignore any recalc events if we have a fullscreen window.
|
// Ignore any recalc events if we have a fullscreen window.
|
||||||
if (PWORKSPACE->m_bHasFullscreenWindow)
|
if (PWORKSPACE->m_bHasFullscreenWindow)
|
||||||
return;
|
return;
|
||||||
@@ -420,6 +454,13 @@ void CHyprDwindleLayout::onBeginDragWindow() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(DRAGGINGWINDOW->m_iWorkspaceID);
|
||||||
|
|
||||||
|
if (PWORKSPACE->m_bHasFullscreenWindow) {
|
||||||
|
Debug::log(LOG, "Rejecting drag on a fullscreen workspace.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
DRAGGINGWINDOW->m_bDraggingTiled = false;
|
DRAGGINGWINDOW->m_bDraggingTiled = false;
|
||||||
|
|
||||||
if (!DRAGGINGWINDOW->m_bIsFloating) {
|
if (!DRAGGINGWINDOW->m_bIsFloating) {
|
||||||
@@ -476,80 +517,7 @@ void CHyprDwindleLayout::onMouseMove(const Vector2D& mousePos) {
|
|||||||
|
|
||||||
g_pXWaylandManager->setWindowSize(DRAGGINGWINDOW, DRAGGINGWINDOW->m_vRealSize.goalv());
|
g_pXWaylandManager->setWindowSize(DRAGGINGWINDOW, DRAGGINGWINDOW->m_vRealSize.goalv());
|
||||||
} else {
|
} else {
|
||||||
// we need to adjust the splitratio
|
resizeActiveWindow(TICKDELTA, DRAGGINGWINDOW);
|
||||||
|
|
||||||
// get some data about our window
|
|
||||||
const auto PNODE = getNodeFromWindow(DRAGGINGWINDOW);
|
|
||||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(DRAGGINGWINDOW->m_iMonitorID);
|
|
||||||
const bool DISPLAYLEFT = STICKS(DRAGGINGWINDOW->m_vPosition.x, PMONITOR->vecPosition.x + PMONITOR->vecReservedTopLeft.x);
|
|
||||||
const bool DISPLAYRIGHT = STICKS(DRAGGINGWINDOW->m_vPosition.x + DRAGGINGWINDOW->m_vSize.x, PMONITOR->vecPosition.x + PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x);
|
|
||||||
const bool DISPLAYTOP = STICKS(DRAGGINGWINDOW->m_vPosition.y, PMONITOR->vecPosition.y + PMONITOR->vecReservedTopLeft.y);
|
|
||||||
const bool DISPLAYBOTTOM = STICKS(DRAGGINGWINDOW->m_vPosition.y + DRAGGINGWINDOW->m_vSize.y, PMONITOR->vecPosition.y + PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y);
|
|
||||||
|
|
||||||
// construct allowed movement
|
|
||||||
Vector2D allowedMovement = TICKDELTA;
|
|
||||||
if (DISPLAYLEFT && DISPLAYRIGHT)
|
|
||||||
allowedMovement.x = 0;
|
|
||||||
|
|
||||||
if (DISPLAYBOTTOM && DISPLAYTOP)
|
|
||||||
allowedMovement.y = 0;
|
|
||||||
|
|
||||||
// get the correct containers to apply splitratio to
|
|
||||||
const auto PPARENT = PNODE->pParent;
|
|
||||||
|
|
||||||
if (!PPARENT)
|
|
||||||
return; // the only window on a workspace, ignore
|
|
||||||
|
|
||||||
const bool PARENTSIDEBYSIDE = !PPARENT->splitTop;
|
|
||||||
|
|
||||||
// Get the parent's parent
|
|
||||||
auto PPARENT2 = PPARENT->pParent;
|
|
||||||
|
|
||||||
// No parent means we have only 2 windows, and thus one axis of freedom
|
|
||||||
if (!PPARENT2) {
|
|
||||||
if (PARENTSIDEBYSIDE) {
|
|
||||||
allowedMovement.x *= 2.f / PPARENT->size.x;
|
|
||||||
PPARENT->splitRatio = std::clamp(PPARENT->splitRatio + allowedMovement.x, (double)0.1f, (double)1.9f);
|
|
||||||
PPARENT->recalcSizePosRecursive();
|
|
||||||
} else {
|
|
||||||
allowedMovement.y *= 2.f / PPARENT->size.y;
|
|
||||||
PPARENT->splitRatio = std::clamp(PPARENT->splitRatio + allowedMovement.y, (double)0.1f, (double)1.9f);
|
|
||||||
PPARENT->recalcSizePosRecursive();
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get first parent with other split
|
|
||||||
while(PPARENT2 && PPARENT2->splitTop == !PARENTSIDEBYSIDE)
|
|
||||||
PPARENT2 = PPARENT2->pParent;
|
|
||||||
|
|
||||||
// no parent, one axis of freedom
|
|
||||||
if (!PPARENT2) {
|
|
||||||
if (PARENTSIDEBYSIDE) {
|
|
||||||
allowedMovement.x *= 2.f / PPARENT->size.x;
|
|
||||||
PPARENT->splitRatio = std::clamp(PPARENT->splitRatio + allowedMovement.x, (double)0.1f, (double)1.9f);
|
|
||||||
PPARENT->recalcSizePosRecursive();
|
|
||||||
} else {
|
|
||||||
allowedMovement.y *= 2.f / PPARENT->size.y;
|
|
||||||
PPARENT->splitRatio = std::clamp(PPARENT->splitRatio + allowedMovement.y, (double)0.1f, (double)1.9f);
|
|
||||||
PPARENT->recalcSizePosRecursive();
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2 axes of freedom
|
|
||||||
const auto SIDECONTAINER = PARENTSIDEBYSIDE ? PPARENT : PPARENT2;
|
|
||||||
const auto TOPCONTAINER = PARENTSIDEBYSIDE ? PPARENT2 : PPARENT;
|
|
||||||
|
|
||||||
allowedMovement.x *= 2.f / SIDECONTAINER->size.x;
|
|
||||||
allowedMovement.y *= 2.f / TOPCONTAINER->size.y;
|
|
||||||
|
|
||||||
SIDECONTAINER->splitRatio = std::clamp(SIDECONTAINER->splitRatio + allowedMovement.x, (double)0.1f, (double)1.9f);
|
|
||||||
TOPCONTAINER->splitRatio = std::clamp(TOPCONTAINER->splitRatio + allowedMovement.y, (double)0.1f, (double)1.9f);
|
|
||||||
SIDECONTAINER->recalcSizePosRecursive();
|
|
||||||
TOPCONTAINER->recalcSizePosRecursive();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -567,6 +535,97 @@ void CHyprDwindleLayout::onMouseMove(const Vector2D& mousePos) {
|
|||||||
g_pHyprRenderer->damageWindow(DRAGGINGWINDOW);
|
g_pHyprRenderer->damageWindow(DRAGGINGWINDOW);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, CWindow* pWindow) {
|
||||||
|
|
||||||
|
const auto PWINDOW = pWindow ? pWindow : g_pCompositor->m_pLastWindow;
|
||||||
|
|
||||||
|
if (!g_pCompositor->windowValidMapped(PWINDOW))
|
||||||
|
return;
|
||||||
|
|
||||||
|
const auto PNODE = getNodeFromWindow(PWINDOW);
|
||||||
|
|
||||||
|
if (!PNODE) {
|
||||||
|
PWINDOW->m_vRealSize.setValueAndWarp(PWINDOW->m_vRealSize.goalv() + pixResize);
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get some data about our window
|
||||||
|
const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID);
|
||||||
|
const bool DISPLAYLEFT = STICKS(PWINDOW->m_vPosition.x, PMONITOR->vecPosition.x + PMONITOR->vecReservedTopLeft.x);
|
||||||
|
const bool DISPLAYRIGHT = STICKS(PWINDOW->m_vPosition.x + PWINDOW->m_vSize.x, PMONITOR->vecPosition.x + PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x);
|
||||||
|
const bool DISPLAYTOP = STICKS(PWINDOW->m_vPosition.y, PMONITOR->vecPosition.y + PMONITOR->vecReservedTopLeft.y);
|
||||||
|
const bool DISPLAYBOTTOM = STICKS(PWINDOW->m_vPosition.y + PWINDOW->m_vSize.y, PMONITOR->vecPosition.y + PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y);
|
||||||
|
|
||||||
|
// construct allowed movement
|
||||||
|
Vector2D allowedMovement = pixResize;
|
||||||
|
if (DISPLAYLEFT && DISPLAYRIGHT)
|
||||||
|
allowedMovement.x = 0;
|
||||||
|
|
||||||
|
if (DISPLAYBOTTOM && DISPLAYTOP)
|
||||||
|
allowedMovement.y = 0;
|
||||||
|
|
||||||
|
// get the correct containers to apply splitratio to
|
||||||
|
const auto PPARENT = PNODE->pParent;
|
||||||
|
|
||||||
|
if (!PPARENT)
|
||||||
|
return; // the only window on a workspace, ignore
|
||||||
|
|
||||||
|
const bool PARENTSIDEBYSIDE = !PPARENT->splitTop;
|
||||||
|
|
||||||
|
// Get the parent's parent
|
||||||
|
auto PPARENT2 = PPARENT->pParent;
|
||||||
|
|
||||||
|
// No parent means we have only 2 windows, and thus one axis of freedom
|
||||||
|
if (!PPARENT2) {
|
||||||
|
if (PARENTSIDEBYSIDE) {
|
||||||
|
allowedMovement.x *= 2.f / PPARENT->size.x;
|
||||||
|
PPARENT->splitRatio = std::clamp(PPARENT->splitRatio + allowedMovement.x, (double)0.1f, (double)1.9f);
|
||||||
|
PPARENT->recalcSizePosRecursive();
|
||||||
|
} else {
|
||||||
|
allowedMovement.y *= 2.f / PPARENT->size.y;
|
||||||
|
PPARENT->splitRatio = std::clamp(PPARENT->splitRatio + allowedMovement.y, (double)0.1f, (double)1.9f);
|
||||||
|
PPARENT->recalcSizePosRecursive();
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get first parent with other split
|
||||||
|
while (PPARENT2 && PPARENT2->splitTop == !PARENTSIDEBYSIDE)
|
||||||
|
PPARENT2 = PPARENT2->pParent;
|
||||||
|
|
||||||
|
// no parent, one axis of freedom
|
||||||
|
if (!PPARENT2) {
|
||||||
|
if (PARENTSIDEBYSIDE) {
|
||||||
|
allowedMovement.x *= 2.f / PPARENT->size.x;
|
||||||
|
PPARENT->splitRatio = std::clamp(PPARENT->splitRatio + allowedMovement.x, (double)0.1f, (double)1.9f);
|
||||||
|
PPARENT->recalcSizePosRecursive();
|
||||||
|
} else {
|
||||||
|
allowedMovement.y *= 2.f / PPARENT->size.y;
|
||||||
|
PPARENT->splitRatio = std::clamp(PPARENT->splitRatio + allowedMovement.y, (double)0.1f, (double)1.9f);
|
||||||
|
PPARENT->recalcSizePosRecursive();
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2 axes of freedom
|
||||||
|
const auto SIDECONTAINER = PARENTSIDEBYSIDE ? PPARENT : PPARENT2;
|
||||||
|
const auto TOPCONTAINER = PARENTSIDEBYSIDE ? PPARENT2 : PPARENT;
|
||||||
|
|
||||||
|
allowedMovement.x *= 2.f / SIDECONTAINER->size.x;
|
||||||
|
allowedMovement.y *= 2.f / TOPCONTAINER->size.y;
|
||||||
|
|
||||||
|
SIDECONTAINER->splitRatio = std::clamp(SIDECONTAINER->splitRatio + allowedMovement.x, (double)0.1f, (double)1.9f);
|
||||||
|
TOPCONTAINER->splitRatio = std::clamp(TOPCONTAINER->splitRatio + allowedMovement.y, (double)0.1f, (double)1.9f);
|
||||||
|
SIDECONTAINER->recalcSizePosRecursive();
|
||||||
|
TOPCONTAINER->recalcSizePosRecursive();
|
||||||
|
}
|
||||||
|
|
||||||
void CHyprDwindleLayout::onWindowCreatedFloating(CWindow* pWindow) {
|
void CHyprDwindleLayout::onWindowCreatedFloating(CWindow* pWindow) {
|
||||||
wlr_box desiredGeometry = {0};
|
wlr_box desiredGeometry = {0};
|
||||||
g_pXWaylandManager->getGeometryForWindow(pWindow, &desiredGeometry);
|
g_pXWaylandManager->getGeometryForWindow(pWindow, &desiredGeometry);
|
||||||
@@ -616,7 +675,7 @@ void CHyprDwindleLayout::onWindowCreatedFloating(CWindow* pWindow) {
|
|||||||
g_pCompositor->moveWindowToTop(pWindow);
|
g_pCompositor->moveWindowToTop(pWindow);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CHyprDwindleLayout::fullscreenRequestForWindow(CWindow* pWindow) {
|
void CHyprDwindleLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscreenMode fullscreenMode) {
|
||||||
if (!g_pCompositor->windowValidMapped(pWindow))
|
if (!g_pCompositor->windowValidMapped(pWindow))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -646,6 +705,8 @@ void CHyprDwindleLayout::fullscreenRequestForWindow(CWindow* pWindow) {
|
|||||||
} else {
|
} else {
|
||||||
// if it now got fullscreen, make it fullscreen
|
// if it now got fullscreen, make it fullscreen
|
||||||
|
|
||||||
|
PWORKSPACE->m_efFullscreenMode = fullscreenMode;
|
||||||
|
|
||||||
// save position and size if floating
|
// save position and size if floating
|
||||||
if (pWindow->m_bIsFloating) {
|
if (pWindow->m_bIsFloating) {
|
||||||
pWindow->m_vPosition = pWindow->m_vRealPosition.vec();
|
pWindow->m_vPosition = pWindow->m_vRealPosition.vec();
|
||||||
@@ -653,8 +714,22 @@ void CHyprDwindleLayout::fullscreenRequestForWindow(CWindow* pWindow) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// apply new pos and size being monitors' box
|
// apply new pos and size being monitors' box
|
||||||
pWindow->m_vRealPosition = PMONITOR->vecPosition;
|
if (fullscreenMode == FULLSCREEN_FULL) {
|
||||||
pWindow->m_vRealSize = PMONITOR->vecSize;
|
pWindow->m_vRealPosition = PMONITOR->vecPosition;
|
||||||
|
pWindow->m_vRealSize = PMONITOR->vecSize;
|
||||||
|
} else {
|
||||||
|
// This is a massive hack.
|
||||||
|
// We make a fake "only" node and apply
|
||||||
|
// To keep consistent with the settings without C+P code
|
||||||
|
|
||||||
|
SDwindleNodeData fakeNode;
|
||||||
|
fakeNode.pWindow = pWindow;
|
||||||
|
fakeNode.position = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft;
|
||||||
|
fakeNode.size = PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight;
|
||||||
|
fakeNode.workspaceID = pWindow->m_iWorkspaceID;
|
||||||
|
|
||||||
|
applyNodeDataToWindow(&fakeNode);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
g_pXWaylandManager->setWindowSize(pWindow, pWindow->m_vRealSize.goalv());
|
g_pXWaylandManager->setWindowSize(pWindow, pWindow->m_vRealSize.goalv());
|
||||||
@@ -693,6 +768,10 @@ void CHyprDwindleLayout::toggleWindowGroup(CWindow* pWindow) {
|
|||||||
for (auto& node : PGROUPPARENT->groupMembers) {
|
for (auto& node : PGROUPPARENT->groupMembers) {
|
||||||
node->pGroupParent = nullptr;
|
node->pGroupParent = nullptr;
|
||||||
node->pWindow->m_cRealBorderColor.setValueAndWarp(INACTIVEBORDERCOL); // no anim here because they pop in
|
node->pWindow->m_cRealBorderColor.setValueAndWarp(INACTIVEBORDERCOL); // no anim here because they pop in
|
||||||
|
|
||||||
|
for (auto& wd : node->pWindow->m_dWindowDecorations) {
|
||||||
|
wd->updateWindow(node->pWindow);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PGROUPPARENT->groupMembers.clear();
|
PGROUPPARENT->groupMembers.clear();
|
||||||
@@ -725,6 +804,8 @@ void CHyprDwindleLayout::toggleWindowGroup(CWindow* pWindow) {
|
|||||||
c->pGroupParent = PPARENT;
|
c->pGroupParent = PPARENT;
|
||||||
c->pWindow->m_cRealBorderColor = GROUPINACTIVEBORDERCOL;
|
c->pWindow->m_cRealBorderColor = GROUPINACTIVEBORDERCOL;
|
||||||
|
|
||||||
|
c->pWindow->m_dWindowDecorations.push_back(std::make_unique<CHyprGroupBarDecoration>(c->pWindow));
|
||||||
|
|
||||||
if (c->pWindow == g_pCompositor->m_pLastWindow)
|
if (c->pWindow == g_pCompositor->m_pLastWindow)
|
||||||
c->pWindow->m_cRealBorderColor = CColor(g_pConfigManager->getInt("dwindle:col.group_border_active"));
|
c->pWindow->m_cRealBorderColor = CColor(g_pConfigManager->getInt("dwindle:col.group_border_active"));
|
||||||
}
|
}
|
||||||
@@ -735,7 +816,32 @@ void CHyprDwindleLayout::toggleWindowGroup(CWindow* pWindow) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CHyprDwindleLayout::switchGroupWindow(CWindow* pWindow) {
|
std::deque<CWindow*> CHyprDwindleLayout::getGroupMembers(CWindow* pWindow) {
|
||||||
|
|
||||||
|
std::deque<CWindow*> result;
|
||||||
|
|
||||||
|
if (!g_pCompositor->windowExists(pWindow))
|
||||||
|
return result; // reject with empty
|
||||||
|
|
||||||
|
// get the node
|
||||||
|
const auto PNODE = getNodeFromWindow(pWindow);
|
||||||
|
|
||||||
|
if (!PNODE)
|
||||||
|
return result; // reject with empty
|
||||||
|
|
||||||
|
const auto PGROUPPARENT = PNODE->pGroupParent;
|
||||||
|
|
||||||
|
if (!PGROUPPARENT)
|
||||||
|
return result; // reject with empty
|
||||||
|
|
||||||
|
for (auto& node : PGROUPPARENT->groupMembers) {
|
||||||
|
result.push_back(node->pWindow);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CHyprDwindleLayout::switchGroupWindow(CWindow* pWindow, bool forward) {
|
||||||
if (!g_pCompositor->windowValidMapped(pWindow))
|
if (!g_pCompositor->windowValidMapped(pWindow))
|
||||||
return; // reject
|
return; // reject
|
||||||
|
|
||||||
@@ -747,13 +853,25 @@ void CHyprDwindleLayout::switchGroupWindow(CWindow* pWindow) {
|
|||||||
if (!PNODE->pGroupParent)
|
if (!PNODE->pGroupParent)
|
||||||
return; // reject
|
return; // reject
|
||||||
|
|
||||||
PNODE->pGroupParent->groupMemberActive++;
|
if (forward)
|
||||||
|
PNODE->pGroupParent->groupMemberActive++;
|
||||||
|
else
|
||||||
|
PNODE->pGroupParent->groupMemberActive--;
|
||||||
|
|
||||||
|
if (PNODE->pGroupParent->groupMemberActive < 0)
|
||||||
|
PNODE->pGroupParent->groupMemberActive = PNODE->pGroupParent->groupMembers.size() - 1;
|
||||||
|
|
||||||
if ((long unsigned int)PNODE->pGroupParent->groupMemberActive >= PNODE->pGroupParent->groupMembers.size())
|
if ((long unsigned int)PNODE->pGroupParent->groupMemberActive >= PNODE->pGroupParent->groupMembers.size())
|
||||||
PNODE->pGroupParent->groupMemberActive = 0;
|
PNODE->pGroupParent->groupMemberActive = 0;
|
||||||
|
|
||||||
PNODE->pGroupParent->recalcSizePosRecursive();
|
PNODE->pGroupParent->recalcSizePosRecursive();
|
||||||
|
|
||||||
|
for (auto& gm : PNODE->pGroupParent->groupMembers) {
|
||||||
|
for (auto& deco : gm->pWindow->m_dWindowDecorations) {
|
||||||
|
deco->updateWindow(gm->pWindow);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// focus
|
// focus
|
||||||
g_pCompositor->focusWindow(PNODE->pGroupParent->groupMembers[PNODE->pGroupParent->groupMemberActive]->pWindow);
|
g_pCompositor->focusWindow(PNODE->pGroupParent->groupMembers[PNODE->pGroupParent->groupMemberActive]->pWindow);
|
||||||
}
|
}
|
||||||
@@ -844,13 +962,21 @@ void CHyprDwindleLayout::alterSplitRatioBy(CWindow* pWindow, float ratio) {
|
|||||||
PNODE->pParent->recalcSizePosRecursive();
|
PNODE->pParent->recalcSizePosRecursive();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CHyprDwindleLayout::layoutMessage(SLayoutMessageHeader header, std::string message) {
|
std::any CHyprDwindleLayout::layoutMessage(SLayoutMessageHeader header, std::string message) {
|
||||||
if (message == "togglegroup")
|
if (message == "togglegroup")
|
||||||
toggleWindowGroup(header.pWindow);
|
toggleWindowGroup(header.pWindow);
|
||||||
else if (message == "changegroupactive")
|
else if (message == "changegroupactivef")
|
||||||
switchGroupWindow(header.pWindow);
|
switchGroupWindow(header.pWindow, true);
|
||||||
|
else if (message == "changegroupactiveb")
|
||||||
|
switchGroupWindow(header.pWindow, false);
|
||||||
else if (message == "togglesplit")
|
else if (message == "togglesplit")
|
||||||
toggleSplit(header.pWindow);
|
toggleSplit(header.pWindow);
|
||||||
|
else if (message == "groupinfo") {
|
||||||
|
auto res = getGroupMembers(g_pCompositor->m_pLastWindow);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
void CHyprDwindleLayout::toggleSplit(CWindow* pWindow) {
|
void CHyprDwindleLayout::toggleSplit(CWindow* pWindow) {
|
||||||
@@ -862,4 +988,8 @@ void CHyprDwindleLayout::toggleSplit(CWindow* pWindow) {
|
|||||||
PNODE->pParent->splitTop = !PNODE->pParent->splitTop;
|
PNODE->pParent->splitTop = !PNODE->pParent->splitTop;
|
||||||
|
|
||||||
PNODE->pParent->recalcSizePosRecursive();
|
PNODE->pParent->recalcSizePosRecursive();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string CHyprDwindleLayout::getLayoutName() {
|
||||||
|
return "dwindle";
|
||||||
}
|
}
|
@@ -3,8 +3,10 @@
|
|||||||
#include "IHyprLayout.hpp"
|
#include "IHyprLayout.hpp"
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <deque>
|
#include <deque>
|
||||||
|
#include "../render/decorations/CHyprGroupBarDecoration.hpp"
|
||||||
|
|
||||||
class CHyprDwindleLayout;
|
class CHyprDwindleLayout;
|
||||||
|
enum eFullscreenMode : uint8_t;
|
||||||
|
|
||||||
struct SDwindleNodeData {
|
struct SDwindleNodeData {
|
||||||
SDwindleNodeData* pParent = nullptr;
|
SDwindleNodeData* pParent = nullptr;
|
||||||
@@ -46,14 +48,16 @@ public:
|
|||||||
virtual void recalculateWindow(CWindow*);
|
virtual void recalculateWindow(CWindow*);
|
||||||
virtual void changeWindowFloatingMode(CWindow*);
|
virtual void changeWindowFloatingMode(CWindow*);
|
||||||
virtual void onBeginDragWindow();
|
virtual void onBeginDragWindow();
|
||||||
|
virtual void resizeActiveWindow(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*);
|
virtual void fullscreenRequestForWindow(CWindow*, eFullscreenMode);
|
||||||
virtual void 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*);
|
||||||
virtual void alterSplitRatioBy(CWindow*, float);
|
virtual void alterSplitRatioBy(CWindow*, float);
|
||||||
|
virtual std::string getLayoutName();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
@@ -71,8 +75,9 @@ public:
|
|||||||
SDwindleNodeData* getMasterNodeOnWorkspace(const int&);
|
SDwindleNodeData* getMasterNodeOnWorkspace(const int&);
|
||||||
|
|
||||||
void toggleWindowGroup(CWindow*);
|
void toggleWindowGroup(CWindow*);
|
||||||
void switchGroupWindow(CWindow*);
|
void switchGroupWindow(CWindow*, bool forward);
|
||||||
void toggleSplit(CWindow*);
|
void toggleSplit(CWindow*);
|
||||||
|
std::deque<CWindow*> getGroupMembers(CWindow*);
|
||||||
|
|
||||||
friend struct SDwindleNodeData;
|
friend struct SDwindleNodeData;
|
||||||
};
|
};
|
@@ -12,6 +12,8 @@ struct SLayoutMessageHeader {
|
|||||||
CWindow* pWindow = nullptr;
|
CWindow* pWindow = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum eFullscreenMode : uint8_t;
|
||||||
|
|
||||||
interface IHyprLayout {
|
interface IHyprLayout {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@@ -47,6 +49,12 @@ public:
|
|||||||
as.
|
as.
|
||||||
*/
|
*/
|
||||||
virtual void onBeginDragWindow() = 0;
|
virtual void onBeginDragWindow() = 0;
|
||||||
|
/*
|
||||||
|
Called when a user requests a resize of the current window by a vec
|
||||||
|
Vector2D holds pixel values
|
||||||
|
Optional pWindow for a specific window
|
||||||
|
*/
|
||||||
|
virtual void resizeActiveWindow(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)
|
||||||
@@ -66,17 +74,18 @@ public:
|
|||||||
virtual void onWindowCreatedFloating(CWindow*) = 0;
|
virtual void onWindowCreatedFloating(CWindow*) = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Called when a window requests to toggle its' fullscreen state.
|
Called when a window / the user requests to toggle the fullscreen state of a window
|
||||||
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*) = 0;
|
virtual void fullscreenRequestForWindow(CWindow*, eFullscreenMode) = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Called when a dispatcher requests a custom message
|
Called when a dispatcher requests a custom message
|
||||||
The layout is free to ignore.
|
The layout is free to ignore.
|
||||||
|
std::any is the reply. Can be empty.
|
||||||
*/
|
*/
|
||||||
virtual void layoutMessage(SLayoutMessageHeader, std::string) = 0;
|
virtual std::any layoutMessage(SLayoutMessageHeader, std::string) = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Required to be handled, but may return just SWindowRenderLayoutHints()
|
Required to be handled, but may return just SWindowRenderLayoutHints()
|
||||||
@@ -96,4 +105,9 @@ public:
|
|||||||
on a window
|
on a window
|
||||||
*/
|
*/
|
||||||
virtual void alterSplitRatioBy(CWindow*, float) = 0;
|
virtual void alterSplitRatioBy(CWindow*, float) = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Called when something wants the current layout's name
|
||||||
|
*/
|
||||||
|
virtual std::string getLayoutName() = 0;
|
||||||
};
|
};
|
11
src/main.cpp
11
src/main.cpp
@@ -3,6 +3,7 @@
|
|||||||
#include "Compositor.hpp"
|
#include "Compositor.hpp"
|
||||||
#include "config/ConfigManager.hpp"
|
#include "config/ConfigManager.hpp"
|
||||||
#include "init/initHelpers.hpp"
|
#include "init/initHelpers.hpp"
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
// I am a bad bad boy and have used some global vars here,
|
// I am a bad bad boy and have used some global vars here,
|
||||||
// just for this file
|
// just for this file
|
||||||
@@ -19,17 +20,19 @@ int main(int argc, char** argv) {
|
|||||||
ignoreSudo = true;
|
ignoreSudo = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
system("mkdir -p /tmp/hypr");
|
||||||
|
|
||||||
if (!ignoreSudo) {
|
if (!ignoreSudo) {
|
||||||
if (Init::isSudo()) {
|
if (Init::isSudo()) {
|
||||||
Debug::log(CRIT, "Hyprland shall not be run as the root user. If you really want to, use the --i-am-really-stupid flag.");
|
std::cout << "Hyprland shall not be run as the root user. If you really want to, use the --i-am-really-stupid flag.\n";
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Debug::log(WARN, "Running with ignored root checks, I surely hope you know what you're doing.");
|
std::cout << "Running with ignored root checks, I surely hope you know what you're doing.\n";
|
||||||
sleep(1);
|
sleep(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug::log(LOG, "Welcome to Hyprland!");
|
std::cout << "Welcome to Hyprland!\n";
|
||||||
|
|
||||||
// let's init the compositor.
|
// let's init the compositor.
|
||||||
// it initializes basic Wayland stuff in the constructor.
|
// it initializes basic Wayland stuff in the constructor.
|
||||||
|
@@ -140,8 +140,12 @@ void CAnimationManager::tick() {
|
|||||||
case AVARDAMAGE_ENTIRE: {
|
case AVARDAMAGE_ENTIRE: {
|
||||||
g_pHyprRenderer->damageBox(&WLRBOXPREV);
|
g_pHyprRenderer->damageBox(&WLRBOXPREV);
|
||||||
|
|
||||||
if (PWINDOW)
|
if (PWINDOW) {
|
||||||
g_pHyprRenderer->damageWindow(PWINDOW);
|
g_pHyprRenderer->damageWindow(PWINDOW);
|
||||||
|
for (auto& wd : PWINDOW->m_dWindowDecorations) {
|
||||||
|
wd->updateWindow(PWINDOW);
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case AVARDAMAGE_BORDER: {
|
case AVARDAMAGE_BORDER: {
|
||||||
@@ -208,15 +212,20 @@ bool CAnimationManager::deltazero(const CColor& a, const CColor& b) {
|
|||||||
//
|
//
|
||||||
//
|
//
|
||||||
|
|
||||||
void CAnimationManager::animationPopin(CWindow* pWindow) {
|
void CAnimationManager::animationPopin(CWindow* pWindow, bool close) {
|
||||||
const auto GOALPOS = pWindow->m_vRealPosition.goalv();
|
const auto GOALPOS = pWindow->m_vRealPosition.goalv();
|
||||||
const auto GOALSIZE = pWindow->m_vRealSize.goalv();
|
const auto GOALSIZE = pWindow->m_vRealSize.goalv();
|
||||||
|
|
||||||
pWindow->m_vRealPosition.setValue(GOALPOS + GOALSIZE / 2.f);
|
if (!close) {
|
||||||
pWindow->m_vRealSize.setValue(Vector2D(5, 5));
|
pWindow->m_vRealPosition.setValue(GOALPOS + GOALSIZE / 2.f);
|
||||||
|
pWindow->m_vRealSize.setValue(Vector2D(5, 5));
|
||||||
|
} else {
|
||||||
|
pWindow->m_vRealPosition = GOALPOS + GOALSIZE / 2.f;
|
||||||
|
pWindow->m_vRealSize = Vector2D(5, 5);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CAnimationManager::animationSlide(CWindow* pWindow, std::string force) {
|
void CAnimationManager::animationSlide(CWindow* pWindow, std::string force, bool close) {
|
||||||
pWindow->m_vRealSize.warp(); // size we preserve in slide
|
pWindow->m_vRealSize.warp(); // size we preserve in slide
|
||||||
|
|
||||||
const auto GOALPOS = pWindow->m_vRealPosition.goalv();
|
const auto GOALPOS = pWindow->m_vRealPosition.goalv();
|
||||||
@@ -224,11 +233,18 @@ void CAnimationManager::animationSlide(CWindow* pWindow, std::string force) {
|
|||||||
|
|
||||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID);
|
const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID);
|
||||||
|
|
||||||
|
Vector2D posOffset;
|
||||||
|
|
||||||
if (force != "") {
|
if (force != "") {
|
||||||
if (force == "bottom") pWindow->m_vRealPosition.setValue(Vector2D(GOALPOS.x, PMONITOR->vecPosition.y + PMONITOR->vecSize.y));
|
if (force == "bottom") posOffset = Vector2D(GOALPOS.x, PMONITOR->vecPosition.y + PMONITOR->vecSize.y);
|
||||||
else if (force == "left") pWindow->m_vRealPosition.setValue(GOALPOS - Vector2D(GOALSIZE.x, 0));
|
else if (force == "left") posOffset = GOALPOS - Vector2D(GOALSIZE.x, 0);
|
||||||
else if (force == "right") pWindow->m_vRealPosition.setValue(GOALPOS + Vector2D(GOALSIZE.x, 0));
|
else if (force == "right") posOffset = GOALPOS + Vector2D(GOALSIZE.x, 0);
|
||||||
else pWindow->m_vRealPosition.setValue(Vector2D(GOALPOS.x, PMONITOR->vecPosition.y - GOALSIZE.y));
|
else posOffset = Vector2D(GOALPOS.x, PMONITOR->vecPosition.y - GOALSIZE.y);
|
||||||
|
|
||||||
|
if (!close)
|
||||||
|
pWindow->m_vRealPosition.setValue(posOffset);
|
||||||
|
else
|
||||||
|
pWindow->m_vRealPosition = posOffset;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -243,25 +259,30 @@ void CAnimationManager::animationSlide(CWindow* pWindow, std::string force) {
|
|||||||
|
|
||||||
if (DISPLAYBOTTOM && DISPLAYTOP) {
|
if (DISPLAYBOTTOM && DISPLAYTOP) {
|
||||||
if (DISPLAYLEFT && DISPLAYRIGHT) {
|
if (DISPLAYLEFT && DISPLAYRIGHT) {
|
||||||
pWindow->m_vRealPosition.setValue(GOALPOS + Vector2D(0, GOALSIZE.y));
|
posOffset = GOALPOS + Vector2D(0, GOALSIZE.y);
|
||||||
} else if (DISPLAYLEFT) {
|
} else if (DISPLAYLEFT) {
|
||||||
pWindow->m_vRealPosition.setValue(GOALPOS - Vector2D(GOALSIZE.x, 0));
|
posOffset = GOALPOS - Vector2D(GOALSIZE.x, 0);
|
||||||
} else {
|
} else {
|
||||||
pWindow->m_vRealPosition.setValue(GOALPOS + Vector2D(GOALSIZE.x, 0));
|
posOffset = GOALPOS + Vector2D(GOALSIZE.x, 0);
|
||||||
}
|
}
|
||||||
} else if (DISPLAYTOP) {
|
} else if (DISPLAYTOP) {
|
||||||
pWindow->m_vRealPosition.setValue(GOALPOS - Vector2D(0, GOALSIZE.y));
|
posOffset = GOALPOS - Vector2D(0, GOALSIZE.y);
|
||||||
} else if (DISPLAYBOTTOM) {
|
} else if (DISPLAYBOTTOM) {
|
||||||
pWindow->m_vRealPosition.setValue(GOALPOS + Vector2D(0, GOALSIZE.y));
|
posOffset = GOALPOS + Vector2D(0, GOALSIZE.y);
|
||||||
} else {
|
} else {
|
||||||
if (MIDPOINT.y > PMONITOR->vecPosition.y + PMONITOR->vecSize.y / 2.f)
|
if (MIDPOINT.y > PMONITOR->vecPosition.y + PMONITOR->vecSize.y / 2.f)
|
||||||
pWindow->m_vRealPosition.setValue(Vector2D(GOALPOS.x, PMONITOR->vecPosition.y + PMONITOR->vecSize.y));
|
posOffset = Vector2D(GOALPOS.x, PMONITOR->vecPosition.y + PMONITOR->vecSize.y);
|
||||||
else
|
else
|
||||||
pWindow->m_vRealPosition.setValue(Vector2D(GOALPOS.x, PMONITOR->vecPosition.y - GOALSIZE.y));
|
posOffset = Vector2D(GOALPOS.x, PMONITOR->vecPosition.y - GOALSIZE.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!close)
|
||||||
|
pWindow->m_vRealPosition.setValue(posOffset);
|
||||||
|
else
|
||||||
|
pWindow->m_vRealPosition = posOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CAnimationManager::onWindowPostCreate(CWindow* pWindow) {
|
void CAnimationManager::onWindowPostCreateClose(CWindow* pWindow, bool close) {
|
||||||
auto ANIMSTYLE = g_pConfigManager->getString("animations:windows_style");
|
auto ANIMSTYLE = g_pConfigManager->getString("animations:windows_style");
|
||||||
transform(ANIMSTYLE.begin(), ANIMSTYLE.end(), ANIMSTYLE.begin(), ::tolower);
|
transform(ANIMSTYLE.begin(), ANIMSTYLE.end(), ANIMSTYLE.begin(), ::tolower);
|
||||||
|
|
||||||
@@ -274,20 +295,20 @@ void CAnimationManager::onWindowPostCreate(CWindow* pWindow) {
|
|||||||
if (pWindow->m_sAdditionalConfigData.animationStyle.find("slide") == 0) {
|
if (pWindow->m_sAdditionalConfigData.animationStyle.find("slide") == 0) {
|
||||||
if (pWindow->m_sAdditionalConfigData.animationStyle.find(' ') != std::string::npos) {
|
if (pWindow->m_sAdditionalConfigData.animationStyle.find(' ') != std::string::npos) {
|
||||||
// has a direction
|
// has a direction
|
||||||
animationSlide(pWindow, pWindow->m_sAdditionalConfigData.animationStyle.substr(pWindow->m_sAdditionalConfigData.animationStyle.find(' ') + 1));
|
animationSlide(pWindow, pWindow->m_sAdditionalConfigData.animationStyle.substr(pWindow->m_sAdditionalConfigData.animationStyle.find(' ') + 1), close);
|
||||||
} else {
|
} else {
|
||||||
animationSlide(pWindow);
|
animationSlide(pWindow, "", close);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// anim popin, fallback
|
// anim popin, fallback
|
||||||
animationPopin(pWindow);
|
animationPopin(pWindow, close);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (ANIMSTYLE == "slide") {
|
if (ANIMSTYLE == "slide") {
|
||||||
animationSlide(pWindow);
|
animationSlide(pWindow, "", close);
|
||||||
} else {
|
} else {
|
||||||
// anim popin, fallback
|
// anim popin, fallback
|
||||||
animationPopin(pWindow);
|
animationPopin(pWindow, close);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -16,7 +16,7 @@ public:
|
|||||||
void addBezierWithName(std::string, const Vector2D&, const Vector2D&);
|
void addBezierWithName(std::string, const Vector2D&, const Vector2D&);
|
||||||
void removeAllBeziers();
|
void removeAllBeziers();
|
||||||
|
|
||||||
void onWindowPostCreate(CWindow*);
|
void onWindowPostCreateClose(CWindow*, bool close = false);
|
||||||
|
|
||||||
std::list<CAnimatedVariable*> m_lAnimatedVariables;
|
std::list<CAnimatedVariable*> m_lAnimatedVariables;
|
||||||
|
|
||||||
@@ -31,8 +31,8 @@ private:
|
|||||||
std::unordered_map<std::string, CBezierCurve> m_mBezierCurves;
|
std::unordered_map<std::string, CBezierCurve> m_mBezierCurves;
|
||||||
|
|
||||||
// Anim stuff
|
// Anim stuff
|
||||||
void animationPopin(CWindow*);
|
void animationPopin(CWindow*, bool close = false);
|
||||||
void animationSlide(CWindow*, std::string force = "");
|
void animationSlide(CWindow*, std::string force = "", bool close = false);
|
||||||
};
|
};
|
||||||
|
|
||||||
inline std::unique_ptr<CAnimationManager> g_pAnimationManager;
|
inline std::unique_ptr<CAnimationManager> g_pAnimationManager;
|
@@ -1,4 +1,5 @@
|
|||||||
#include "EventManager.hpp"
|
#include "EventManager.hpp"
|
||||||
|
#include "../Compositor.hpp"
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
@@ -26,10 +27,9 @@ void CEventManager::startThread() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
unlink("/tmp/hypr/.socket2.sock");
|
|
||||||
|
|
||||||
sockaddr_un SERVERADDRESS = {.sun_family = AF_UNIX};
|
sockaddr_un SERVERADDRESS = {.sun_family = AF_UNIX};
|
||||||
strcpy(SERVERADDRESS.sun_path, "/tmp/hypr/.socket2.sock");
|
std::string socketPath = "/tmp/hypr/" + g_pCompositor->m_szInstanceSignature + "/.socket2.sock";
|
||||||
|
strcpy(SERVERADDRESS.sun_path, socketPath.c_str());
|
||||||
|
|
||||||
bind(SOCKET, (sockaddr*)&SERVERADDRESS, SUN_LEN(&SERVERADDRESS));
|
bind(SOCKET, (sockaddr*)&SERVERADDRESS, SUN_LEN(&SERVERADDRESS));
|
||||||
|
|
||||||
@@ -41,7 +41,7 @@ void CEventManager::startThread() {
|
|||||||
sockaddr_in clientAddress;
|
sockaddr_in clientAddress;
|
||||||
socklen_t clientSize = sizeof(clientAddress);
|
socklen_t clientSize = sizeof(clientAddress);
|
||||||
|
|
||||||
Debug::log(LOG, "Hypr socket 2 started.");
|
Debug::log(LOG, "Hypr socket 2 started at %s", socketPath.c_str());
|
||||||
|
|
||||||
// set the socket nonblock
|
// set the socket nonblock
|
||||||
int flags = fcntl(SOCKET, F_GETFL, 0);
|
int flags = fcntl(SOCKET, F_GETFL, 0);
|
||||||
|
@@ -5,12 +5,14 @@ void CInputManager::onMouseMoved(wlr_pointer_motion_event* e) {
|
|||||||
|
|
||||||
float sensitivity = g_pConfigManager->getFloat("general:sensitivity");
|
float sensitivity = g_pConfigManager->getFloat("general:sensitivity");
|
||||||
|
|
||||||
if (g_pConfigManager->getInt("general:apply_sens_to_raw") == 1)
|
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);
|
||||||
wlr_relative_pointer_manager_v1_send_relative_motion(g_pCompositor->m_sWLRRelPointerMgr, g_pCompositor->m_sSeat.seat, (uint64_t)e->time_msec * 1000, e->delta_x * sensitivity, e->delta_y * sensitivity, e->unaccel_dx * sensitivity, e->unaccel_dy * sensitivity);
|
|
||||||
else
|
|
||||||
wlr_relative_pointer_manager_v1_send_relative_motion(g_pCompositor->m_sWLRRelPointerMgr, g_pCompositor->m_sSeat.seat, (uint64_t)e->time_msec * 1000, e->delta_x, e->delta_y, e->unaccel_dx, e->unaccel_dy);
|
|
||||||
|
|
||||||
wlr_cursor_move(g_pCompositor->m_sWLRCursor, &e->pointer->base, e->delta_x * sensitivity, e->delta_y * sensitivity);
|
if (g_pConfigManager->getInt("general:apply_sens_to_raw") == 1)
|
||||||
|
wlr_relative_pointer_manager_v1_send_relative_motion(g_pCompositor->m_sWLRRelPointerMgr, g_pCompositor->m_sSeat.seat, (uint64_t)e->time_msec * 1000, DELTA.x * sensitivity, DELTA.y * sensitivity, e->unaccel_dx * sensitivity, e->unaccel_dy * sensitivity);
|
||||||
|
else
|
||||||
|
wlr_relative_pointer_manager_v1_send_relative_motion(g_pCompositor->m_sWLRRelPointerMgr, g_pCompositor->m_sSeat.seat, (uint64_t)e->time_msec * 1000, DELTA.x, DELTA.y, e->unaccel_dx, e->unaccel_dy);
|
||||||
|
|
||||||
|
wlr_cursor_move(g_pCompositor->m_sWLRCursor, &e->pointer->base, DELTA.x * sensitivity, DELTA.y * sensitivity);
|
||||||
|
|
||||||
mouseMoveUnified(e->time_msec);
|
mouseMoveUnified(e->time_msec);
|
||||||
}
|
}
|
||||||
@@ -105,7 +107,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
|||||||
|
|
||||||
// then, we check if the workspace doesnt have a fullscreen window
|
// then, we check if the workspace doesnt have a fullscreen window
|
||||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(PMONITOR->activeWorkspace);
|
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(PMONITOR->activeWorkspace);
|
||||||
if (PWORKSPACE->m_bHasFullscreenWindow && !foundSurface) {
|
if (PWORKSPACE->m_bHasFullscreenWindow && !foundSurface && PWORKSPACE->m_efFullscreenMode == FULLSCREEN_FULL) {
|
||||||
pFoundWindow = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID);
|
pFoundWindow = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID);
|
||||||
foundSurface = g_pXWaylandManager->getWindowSurface(pFoundWindow);
|
foundSurface = g_pXWaylandManager->getWindowSurface(pFoundWindow);
|
||||||
surfacePos = pFoundWindow->m_vRealPosition.vec();
|
surfacePos = pFoundWindow->m_vRealPosition.vec();
|
||||||
@@ -113,7 +115,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
|||||||
// only check floating because tiled cant be over fullscreen
|
// only check floating because tiled cant be over fullscreen
|
||||||
for (auto w = g_pCompositor->m_lWindows.rbegin(); w != g_pCompositor->m_lWindows.rend(); w++) {
|
for (auto w = g_pCompositor->m_lWindows.rbegin(); w != g_pCompositor->m_lWindows.rend(); w++) {
|
||||||
wlr_box box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y};
|
wlr_box box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y};
|
||||||
if (w->m_bIsFloating && w->m_bIsMapped && w->m_bCreatedOverFullscreen && wlr_box_contains_point(&box, mouseCoords.x, mouseCoords.y) && g_pCompositor->isWorkspaceVisible(w->m_iWorkspaceID) && !w->m_bHidden) {
|
if (((w->m_bIsFloating && w->m_bIsMapped && w->m_bCreatedOverFullscreen) || (w->m_iWorkspaceID == SPECIAL_WORKSPACE_ID && PMONITOR->specialWorkspaceOpen)) && wlr_box_contains_point(&box, mouseCoords.x, mouseCoords.y) && g_pCompositor->isWorkspaceVisible(w->m_iWorkspaceID) && !w->m_bHidden) {
|
||||||
pFoundWindow = &(*w);
|
pFoundWindow = &(*w);
|
||||||
|
|
||||||
if (!pFoundWindow->m_bIsX11) {
|
if (!pFoundWindow->m_bIsX11) {
|
||||||
@@ -221,7 +223,6 @@ void CInputManager::onMouseButton(wlr_pointer_button_event* e) {
|
|||||||
// notify app if we didnt handle it
|
// notify app if we didnt handle it
|
||||||
if (g_pCompositor->doesSeatAcceptInput(g_pCompositor->m_pLastFocus)) {
|
if (g_pCompositor->doesSeatAcceptInput(g_pCompositor->m_pLastFocus)) {
|
||||||
wlr_seat_pointer_notify_button(g_pCompositor->m_sSeat.seat, e->time_msec, e->button, e->state);
|
wlr_seat_pointer_notify_button(g_pCompositor->m_sSeat.seat, e->time_msec, e->button, e->state);
|
||||||
Debug::log(LOG, "Seat notified of button %i (state %i) on surface %x", e->button, e->state, g_pCompositor->m_pLastFocus);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -237,28 +238,24 @@ void CInputManager::newKeyboard(wlr_input_device* keyboard) {
|
|||||||
|
|
||||||
PNEWKEYBOARD->keyboard = keyboard;
|
PNEWKEYBOARD->keyboard = keyboard;
|
||||||
|
|
||||||
xkb_rule_names rules;
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
const auto REPEATRATE = g_pConfigManager->getInt("input:repeat_rate");
|
const auto REPEATRATE = g_pConfigManager->getInt("input:repeat_rate");
|
||||||
const auto REPEATDELAY = g_pConfigManager->getInt("input:repeat_delay");
|
const auto REPEATDELAY = g_pConfigManager->getInt("input:repeat_delay");
|
||||||
|
|
||||||
wlr_keyboard_set_keymap(keyboard->keyboard, KEYMAP);
|
|
||||||
xkb_keymap_unref(KEYMAP);
|
|
||||||
xkb_context_unref(CONTEXT);
|
|
||||||
wlr_keyboard_set_repeat_info(keyboard->keyboard, std::max(0, REPEATRATE), std::max(0, REPEATDELAY));
|
wlr_keyboard_set_repeat_info(keyboard->keyboard, std::max(0, REPEATRATE), std::max(0, REPEATDELAY));
|
||||||
|
|
||||||
PNEWKEYBOARD->hyprListener_keyboardMod.initCallback(&keyboard->keyboard->events.modifiers, &Events::listener_keyboardMod, PNEWKEYBOARD, "Keyboard");
|
PNEWKEYBOARD->hyprListener_keyboardMod.initCallback(&keyboard->keyboard->events.modifiers, &Events::listener_keyboardMod, PNEWKEYBOARD, "Keyboard");
|
||||||
PNEWKEYBOARD->hyprListener_keyboardKey.initCallback(&keyboard->keyboard->events.key, &Events::listener_keyboardKey, PNEWKEYBOARD, "Keyboard");
|
PNEWKEYBOARD->hyprListener_keyboardKey.initCallback(&keyboard->keyboard->events.key, &Events::listener_keyboardKey, PNEWKEYBOARD, "Keyboard");
|
||||||
PNEWKEYBOARD->hyprListener_keyboardDestroy.initCallback(&keyboard->events.destroy, &Events::listener_keyboardDestroy, PNEWKEYBOARD, "Keyboard");
|
PNEWKEYBOARD->hyprListener_keyboardDestroy.initCallback(&keyboard->events.destroy, &Events::listener_keyboardDestroy, PNEWKEYBOARD, "Keyboard");
|
||||||
|
|
||||||
|
if (m_pActiveKeyboard)
|
||||||
|
m_pActiveKeyboard->active = false;
|
||||||
|
m_pActiveKeyboard = PNEWKEYBOARD;
|
||||||
|
|
||||||
|
setKeyboardLayout();
|
||||||
|
|
||||||
wlr_seat_set_keyboard(g_pCompositor->m_sSeat.seat, keyboard->keyboard);
|
wlr_seat_set_keyboard(g_pCompositor->m_sSeat.seat, keyboard->keyboard);
|
||||||
|
|
||||||
Debug::log(LOG, "New keyboard created, pointers Hypr: %x and WLR: %x", PNEWKEYBOARD, keyboard);
|
Debug::log(LOG, "New keyboard created, pointers Hypr: %x and WLR: %x", PNEWKEYBOARD, keyboard);
|
||||||
|
|
||||||
setKeyboardLayout();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CInputManager::setKeyboardLayout() {
|
void CInputManager::setKeyboardLayout() {
|
||||||
@@ -286,9 +283,31 @@ void CInputManager::setKeyboardLayout() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: configure devices one by one
|
const auto PLASTKEEB = m_pActiveKeyboard->keyboard->keyboard;
|
||||||
for (auto& k : m_lKeyboards)
|
|
||||||
wlr_keyboard_set_keymap(k.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};
|
||||||
|
|
||||||
|
if (g_pConfigManager->getInt("input:numlock_by_default") == 1) {
|
||||||
|
// lock numlock
|
||||||
|
const auto IDX = xkb_map_mod_get_index(KEYMAP, XKB_MOD_NAME_NUM);
|
||||||
|
|
||||||
|
if (IDX != XKB_MOD_INVALID)
|
||||||
|
wlrMods.locked |= (uint32_t)1 << IDX;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wlrMods.locked != 0) {
|
||||||
|
wlr_seat_keyboard_notify_modifiers(g_pCompositor->m_sSeat.seat, &wlrMods);
|
||||||
|
}
|
||||||
|
|
||||||
xkb_keymap_unref(KEYMAP);
|
xkb_keymap_unref(KEYMAP);
|
||||||
xkb_context_unref(CONTEXT);
|
xkb_context_unref(CONTEXT);
|
||||||
@@ -331,6 +350,17 @@ void CInputManager::destroyKeyboard(SKeyboard* pKeyboard) {
|
|||||||
pKeyboard->hyprListener_keyboardMod.removeCallback();
|
pKeyboard->hyprListener_keyboardMod.removeCallback();
|
||||||
pKeyboard->hyprListener_keyboardKey.removeCallback();
|
pKeyboard->hyprListener_keyboardKey.removeCallback();
|
||||||
|
|
||||||
|
if (pKeyboard->active) {
|
||||||
|
m_lKeyboards.remove(*pKeyboard);
|
||||||
|
|
||||||
|
if (m_lKeyboards.size() > 0) {
|
||||||
|
m_pActiveKeyboard = &m_lKeyboards.back();
|
||||||
|
m_pActiveKeyboard->active = true;
|
||||||
|
} else {
|
||||||
|
m_pActiveKeyboard = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
m_lKeyboards.remove(*pKeyboard);
|
m_lKeyboards.remove(*pKeyboard);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -360,8 +390,6 @@ void CInputManager::onKeyboardKey(wlr_keyboard_key_event* e, SKeyboard* pKeyboar
|
|||||||
|
|
||||||
bool found = false;
|
bool found = false;
|
||||||
if (e->state == WL_KEYBOARD_KEY_STATE_PRESSED) {
|
if (e->state == WL_KEYBOARD_KEY_STATE_PRESSED) {
|
||||||
Debug::log(LOG, "Pressed key %i, with the MODMASK being %i", e->keycode, MODS);
|
|
||||||
|
|
||||||
for (int i = 0; i < syms; ++i)
|
for (int i = 0; i < syms; ++i)
|
||||||
found = g_pKeybindManager->handleKeybinds(MODS, keysyms[i]) || found;
|
found = g_pKeybindManager->handleKeybinds(MODS, keysyms[i]) || found;
|
||||||
} else if (e->state == WL_KEYBOARD_KEY_STATE_RELEASED) {
|
} else if (e->state == WL_KEYBOARD_KEY_STATE_RELEASED) {
|
||||||
|
@@ -36,12 +36,13 @@ public:
|
|||||||
|
|
||||||
SDrag m_sDrag;
|
SDrag m_sDrag;
|
||||||
|
|
||||||
std::list<SConstraint> m_lConstraints;
|
std::list<SConstraint> m_lConstraints;
|
||||||
|
std::list<SKeyboard> m_lKeyboards;
|
||||||
|
std::list<SMouse> m_lMice;
|
||||||
|
|
||||||
private:
|
SKeyboard* m_pActiveKeyboard = nullptr;
|
||||||
|
|
||||||
std::list<SKeyboard> m_lKeyboards;
|
private:
|
||||||
std::list<SMouse> m_lMice;
|
|
||||||
|
|
||||||
void mouseMoveUnified(uint32_t, bool refocus = false);
|
void mouseMoveUnified(uint32_t, bool refocus = false);
|
||||||
};
|
};
|
||||||
|
@@ -20,6 +20,12 @@ CKeybindManager::CKeybindManager() {
|
|||||||
m_mDispatchers["focusmonitor"] = focusMonitor;
|
m_mDispatchers["focusmonitor"] = focusMonitor;
|
||||||
m_mDispatchers["movecursortocorner"] = moveCursorToCorner;
|
m_mDispatchers["movecursortocorner"] = moveCursorToCorner;
|
||||||
m_mDispatchers["workspaceopt"] = workspaceOpt;
|
m_mDispatchers["workspaceopt"] = workspaceOpt;
|
||||||
|
m_mDispatchers["exit"] = exitHyprland;
|
||||||
|
m_mDispatchers["movecurrentworkspacetomonitor"] = moveCurrentWorkspaceToMonitor;
|
||||||
|
m_mDispatchers["moveworkspacetomonitor"] = moveWorkspaceToMonitor;
|
||||||
|
m_mDispatchers["togglespecialworkspace"] = toggleSpecialWorkspace;
|
||||||
|
m_mDispatchers["forcerendererreload"] = forceRendererReload;
|
||||||
|
m_mDispatchers["resizeactive"] = resizeActive;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CKeybindManager::addKeybind(SKeybind kb) {
|
void CKeybindManager::addKeybind(SKeybind kb) {
|
||||||
@@ -88,6 +94,7 @@ bool CKeybindManager::handleKeybinds(const uint32_t& modmask, const xkb_keysym_t
|
|||||||
Debug::log(ERR, "Inavlid handler in a keybind! (handler %s does not exist)", k.handler.c_str());
|
Debug::log(ERR, "Inavlid handler in a keybind! (handler %s does not exist)", k.handler.c_str());
|
||||||
} else {
|
} else {
|
||||||
// call the dispatcher
|
// call the dispatcher
|
||||||
|
Debug::log(LOG, "Keybind triggered, calling dispatcher (%d, %d)", modmask, KBKEYUPPER);
|
||||||
DISPATCHER->second(k.arg);
|
DISPATCHER->second(k.arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -104,8 +111,17 @@ bool CKeybindManager::handleInternalKeybinds(xkb_keysym_t keysym) {
|
|||||||
|
|
||||||
const auto PSESSION = wlr_backend_get_session(g_pCompositor->m_sWLRBackend);
|
const auto PSESSION = wlr_backend_get_session(g_pCompositor->m_sWLRBackend);
|
||||||
if (PSESSION) {
|
if (PSESSION) {
|
||||||
const auto TTY = keysym - XKB_KEY_XF86Switch_VT_1 + 1;
|
const int TTY = keysym - XKB_KEY_XF86Switch_VT_1 + 1;
|
||||||
wlr_session_change_vt(PSESSION, TTY);
|
wlr_session_change_vt(PSESSION, TTY);
|
||||||
|
|
||||||
|
for (auto& m : g_pCompositor->m_lMonitors) {
|
||||||
|
g_pHyprOpenGL->destroyMonitorResources(&m); // mark resources as unusable anymore
|
||||||
|
m.noFrameSchedule = true;
|
||||||
|
m.framesToSkip = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
Debug::log(LOG, "Switched to VT %i, destroyed all render data, frames to skip for each: 2", TTY);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,6 +165,10 @@ void CKeybindManager::toggleActiveFloating(std::string args) {
|
|||||||
if (g_pCompositor->windowValidMapped(ACTIVEWINDOW)) {
|
if (g_pCompositor->windowValidMapped(ACTIVEWINDOW)) {
|
||||||
ACTIVEWINDOW->m_bIsFloating = !ACTIVEWINDOW->m_bIsFloating;
|
ACTIVEWINDOW->m_bIsFloating = !ACTIVEWINDOW->m_bIsFloating;
|
||||||
|
|
||||||
|
if (ACTIVEWINDOW->m_iWorkspaceID == SPECIAL_WORKSPACE_ID) {
|
||||||
|
moveActiveToWorkspace(std::to_string(g_pCompositor->getMonitorFromID(ACTIVEWINDOW->m_iMonitorID)->activeWorkspace));
|
||||||
|
}
|
||||||
|
|
||||||
ACTIVEWINDOW->m_vRealPosition.setValue(ACTIVEWINDOW->m_vRealPosition.vec() + Vector2D(5, 5));
|
ACTIVEWINDOW->m_vRealPosition.setValue(ACTIVEWINDOW->m_vRealPosition.vec() + Vector2D(5, 5));
|
||||||
ACTIVEWINDOW->m_vSize = ACTIVEWINDOW->m_vRealPosition.vec() - Vector2D(10, 10);
|
ACTIVEWINDOW->m_vSize = ACTIVEWINDOW->m_vRealPosition.vec() - Vector2D(10, 10);
|
||||||
|
|
||||||
@@ -187,12 +207,20 @@ void CKeybindManager::changeworkspace(std::string args) {
|
|||||||
|
|
||||||
const auto PWORKSPACETOCHANGETO = g_pCompositor->getWorkspaceByID(workspaceToChangeTo);
|
const auto PWORKSPACETOCHANGETO = g_pCompositor->getWorkspaceByID(workspaceToChangeTo);
|
||||||
|
|
||||||
|
if (workspaceToChangeTo == SPECIAL_WORKSPACE_ID)
|
||||||
|
PWORKSPACETOCHANGETO->m_iMonitorID = PMONITOR->ID;
|
||||||
|
|
||||||
// if it's not visible, make it visible.
|
// if it's not visible, make it visible.
|
||||||
if (!g_pCompositor->isWorkspaceVisible(workspaceToChangeTo)) {
|
if (!g_pCompositor->isWorkspaceVisible(workspaceToChangeTo)) {
|
||||||
const auto OLDWORKSPACEID = PMONITOR->activeWorkspace;
|
const auto OLDWORKSPACEID = PMONITOR->activeWorkspace;
|
||||||
|
|
||||||
// change it
|
// change it
|
||||||
PMONITOR->activeWorkspace = workspaceToChangeTo;
|
PMONITOR->specialWorkspaceOpen = false;
|
||||||
|
|
||||||
|
if (workspaceToChangeTo != SPECIAL_WORKSPACE_ID)
|
||||||
|
PMONITOR->activeWorkspace = workspaceToChangeTo;
|
||||||
|
else
|
||||||
|
PMONITOR->specialWorkspaceOpen = true;
|
||||||
|
|
||||||
// we need to move XWayland windows to narnia or otherwise they will still process our cursor and shit
|
// we need to move XWayland windows to narnia or otherwise they will still process our cursor and shit
|
||||||
// and that'd be annoying as hell
|
// and that'd be annoying as hell
|
||||||
@@ -215,7 +243,6 @@ void CKeybindManager::changeworkspace(std::string args) {
|
|||||||
if (!m_bSuppressWorkspaceChangeEvents)
|
if (!m_bSuppressWorkspaceChangeEvents)
|
||||||
g_pEventManager->postEvent(SHyprIPCEvent("workspace", PWORKSPACETOCHANGETO->m_szName));
|
g_pEventManager->postEvent(SHyprIPCEvent("workspace", PWORKSPACETOCHANGETO->m_szName));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// If the monitor is not the one our cursor's at, warp to it.
|
// If the monitor is not the one our cursor's at, warp to it.
|
||||||
if (PMONITOR != g_pCompositor->getMonitorFromCursor()) {
|
if (PMONITOR != g_pCompositor->getMonitorFromCursor()) {
|
||||||
@@ -230,6 +257,9 @@ void CKeybindManager::changeworkspace(std::string args) {
|
|||||||
g_pCompositor->deactivateAllWLRWorkspaces(PWORKSPACETOCHANGETO->m_pWlrHandle);
|
g_pCompositor->deactivateAllWLRWorkspaces(PWORKSPACETOCHANGETO->m_pWlrHandle);
|
||||||
PWORKSPACETOCHANGETO->setActive(true);
|
PWORKSPACETOCHANGETO->setActive(true);
|
||||||
|
|
||||||
|
// recalc layout
|
||||||
|
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PWORKSPACETOCHANGETO->m_iMonitorID);
|
||||||
|
|
||||||
Debug::log(LOG, "Changed to workspace %i", workspaceToChangeTo);
|
Debug::log(LOG, "Changed to workspace %i", workspaceToChangeTo);
|
||||||
|
|
||||||
// focus
|
// focus
|
||||||
@@ -250,22 +280,29 @@ void CKeybindManager::changeworkspace(std::string args) {
|
|||||||
const auto ANIMTOLEFT = workspaceToChangeTo > OLDWORKSPACE;
|
const auto ANIMTOLEFT = workspaceToChangeTo > OLDWORKSPACE;
|
||||||
|
|
||||||
// start anim on old workspace
|
// start anim on old workspace
|
||||||
g_pCompositor->getWorkspaceByID(OLDWORKSPACE)->startAnim(false, ANIMTOLEFT);
|
if (const auto POLDWORKSPACE = g_pCompositor->getWorkspaceByID(OLDWORKSPACE); POLDWORKSPACE)
|
||||||
|
POLDWORKSPACE->startAnim(false, ANIMTOLEFT);
|
||||||
|
|
||||||
g_pCompositor->m_lWorkspaces.emplace_back(PMONITOR->ID);
|
g_pCompositor->m_lWorkspaces.emplace_back(PMONITOR->ID, workspaceToChangeTo == SPECIAL_WORKSPACE_ID);
|
||||||
const auto PWORKSPACE = &g_pCompositor->m_lWorkspaces.back();
|
const auto PWORKSPACE = &g_pCompositor->m_lWorkspaces.back();
|
||||||
|
|
||||||
// start anim on new workspace
|
// start anim on new workspace
|
||||||
PWORKSPACE->startAnim(true, ANIMTOLEFT);
|
PWORKSPACE->startAnim(true, ANIMTOLEFT);
|
||||||
|
|
||||||
// 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(PWORKSPACE->m_pWlrHandle, workspaceName.c_str());
|
if (workspaceToChangeTo != SPECIAL_WORKSPACE_ID)
|
||||||
|
wlr_ext_workspace_handle_v1_set_name(PWORKSPACE->m_pWlrHandle, workspaceName.c_str());
|
||||||
|
|
||||||
PWORKSPACE->m_iID = workspaceToChangeTo;
|
PWORKSPACE->m_iID = workspaceToChangeTo;
|
||||||
PWORKSPACE->m_iMonitorID = PMONITOR->ID;
|
PWORKSPACE->m_iMonitorID = PMONITOR->ID;
|
||||||
PWORKSPACE->m_szName = workspaceName;
|
PWORKSPACE->m_szName = workspaceName;
|
||||||
|
|
||||||
PMONITOR->activeWorkspace = workspaceToChangeTo;
|
PMONITOR->specialWorkspaceOpen = false;
|
||||||
|
|
||||||
|
if (workspaceToChangeTo != SPECIAL_WORKSPACE_ID)
|
||||||
|
PMONITOR->activeWorkspace = workspaceToChangeTo;
|
||||||
|
else
|
||||||
|
PMONITOR->specialWorkspaceOpen = true;
|
||||||
|
|
||||||
// we need to move XWayland windows to narnia or otherwise they will still process our cursor and shit
|
// we need to move XWayland windows to narnia or otherwise they will still process our cursor and shit
|
||||||
// and that'd be annoying as hell
|
// and that'd be annoying as hell
|
||||||
@@ -294,9 +331,9 @@ void CKeybindManager::fullscreenActive(std::string args) {
|
|||||||
if (!g_pCompositor->windowValidMapped(PWINDOW))
|
if (!g_pCompositor->windowValidMapped(PWINDOW))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
g_pLayoutManager->getCurrentLayout()->fullscreenRequestForWindow(PWINDOW);
|
g_pLayoutManager->getCurrentLayout()->fullscreenRequestForWindow(PWINDOW, args == "1" ? eFullscreenMode::FULLSCREEN_MAXIMIZED : eFullscreenMode::FULLSCREEN_FULL);
|
||||||
|
|
||||||
g_pXWaylandManager->setWindowFullscreen(PWINDOW, PWINDOW->m_bIsFullscreen);
|
g_pXWaylandManager->setWindowFullscreen(PWINDOW, PWINDOW->m_bIsFullscreen && args == "0");
|
||||||
|
|
||||||
// make all windows on the same workspace under the fullscreen window
|
// make all windows on the same workspace under the fullscreen window
|
||||||
for (auto& w : g_pCompositor->m_lWindows) {
|
for (auto& w : g_pCompositor->m_lWindows) {
|
||||||
@@ -311,20 +348,33 @@ void CKeybindManager::moveActiveToWorkspace(std::string args) {
|
|||||||
if (!g_pCompositor->windowValidMapped(PWINDOW))
|
if (!g_pCompositor->windowValidMapped(PWINDOW))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
g_pLayoutManager->getCurrentLayout()->onWindowRemoved(PWINDOW);
|
|
||||||
|
|
||||||
const auto OLDWORKSPACE = g_pCompositor->getWorkspaceByID(PWINDOW->m_iWorkspaceID);
|
const auto OLDWORKSPACE = g_pCompositor->getWorkspaceByID(PWINDOW->m_iWorkspaceID);
|
||||||
|
|
||||||
// hack
|
// hack
|
||||||
|
std::string unusedName;
|
||||||
|
const auto WORKSPACEID = getWorkspaceIDFromString(args, unusedName);
|
||||||
|
|
||||||
|
if (WORKSPACEID == PWINDOW->m_iWorkspaceID) {
|
||||||
|
Debug::log(LOG, "Not moving to workspace because it didn't change.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_pLayoutManager->getCurrentLayout()->onWindowRemoved(PWINDOW);
|
||||||
|
|
||||||
g_pKeybindManager->changeworkspace(args);
|
g_pKeybindManager->changeworkspace(args);
|
||||||
|
|
||||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByString(args);
|
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(WORKSPACEID);
|
||||||
|
|
||||||
if (PWORKSPACE == OLDWORKSPACE) {
|
if (PWORKSPACE == OLDWORKSPACE) {
|
||||||
Debug::log(LOG, "Not moving to workspace because it didn't change.");
|
Debug::log(LOG, "Not moving to workspace because it didn't change.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!PWORKSPACE) {
|
||||||
|
Debug::log(ERR, "Workspace null in moveActiveToWorkspace?");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
OLDWORKSPACE->m_bHasFullscreenWindow = false;
|
OLDWORKSPACE->m_bHasFullscreenWindow = false;
|
||||||
|
|
||||||
PWINDOW->m_iWorkspaceID = PWORKSPACE->m_iID;
|
PWINDOW->m_iWorkspaceID = PWORKSPACE->m_iID;
|
||||||
@@ -352,6 +402,17 @@ void CKeybindManager::moveActiveToWorkspace(std::string args) {
|
|||||||
PWINDOW->m_vRealPosition.setValue(PWINDOW->m_vRealPosition.vec() + g_pCompositor->getMonitorFromID(PWORKSPACE->m_iMonitorID)->vecPosition);
|
PWINDOW->m_vRealPosition.setValue(PWINDOW->m_vRealPosition.vec() + g_pCompositor->getMonitorFromID(PWORKSPACE->m_iMonitorID)->vecPosition);
|
||||||
PWINDOW->m_vPosition = PWINDOW->m_vRealPosition.vec();
|
PWINDOW->m_vPosition = PWINDOW->m_vRealPosition.vec();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// undo the damage if we are moving to the special workspace
|
||||||
|
if (WORKSPACEID == SPECIAL_WORKSPACE_ID) {
|
||||||
|
changeworkspace(std::to_string(OLDWORKSPACE->m_iID));
|
||||||
|
OLDWORKSPACE->startAnim(true, true, true);
|
||||||
|
toggleSpecialWorkspace("");
|
||||||
|
g_pCompositor->getWorkspaceByID(SPECIAL_WORKSPACE_ID)->startAnim(false, false, true);
|
||||||
|
|
||||||
|
for (auto& m : g_pCompositor->m_lMonitors)
|
||||||
|
m.specialWorkspaceOpen = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CKeybindManager::moveActiveToWorkspaceSilent(std::string args) {
|
void CKeybindManager::moveActiveToWorkspaceSilent(std::string args) {
|
||||||
@@ -503,7 +564,10 @@ void CKeybindManager::toggleGroup(std::string args) {
|
|||||||
void CKeybindManager::changeGroupActive(std::string args) {
|
void CKeybindManager::changeGroupActive(std::string args) {
|
||||||
SLayoutMessageHeader header;
|
SLayoutMessageHeader header;
|
||||||
header.pWindow = g_pCompositor->m_pLastWindow;
|
header.pWindow = g_pCompositor->m_pLastWindow;
|
||||||
g_pLayoutManager->getCurrentLayout()->layoutMessage(header, "changegroupactive");
|
if (args == "b")
|
||||||
|
g_pLayoutManager->getCurrentLayout()->layoutMessage(header, "changegroupactiveb");
|
||||||
|
else
|
||||||
|
g_pLayoutManager->getCurrentLayout()->layoutMessage(header, "changegroupactivef");
|
||||||
}
|
}
|
||||||
|
|
||||||
void CKeybindManager::toggleSplit(std::string args) {
|
void CKeybindManager::toggleSplit(std::string args) {
|
||||||
@@ -558,7 +622,12 @@ void CKeybindManager::focusMonitor(std::string arg) {
|
|||||||
if (isDirection(arg)) {
|
if (isDirection(arg)) {
|
||||||
const auto PMONITOR = g_pCompositor->getMonitorInDirection(arg[0]);
|
const auto PMONITOR = g_pCompositor->getMonitorInDirection(arg[0]);
|
||||||
if (PMONITOR) {
|
if (PMONITOR) {
|
||||||
changeworkspace(std::to_string(PMONITOR->activeWorkspace));
|
if (PMONITOR->activeWorkspace < 0) {
|
||||||
|
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(PMONITOR->activeWorkspace);
|
||||||
|
changeworkspace("name:" + PWORKSPACE->m_szName);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
changeworkspace(std::to_string(PMONITOR->activeWorkspace));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -666,4 +735,133 @@ void CKeybindManager::workspaceOpt(std::string args) {
|
|||||||
|
|
||||||
// recalc mon
|
// recalc mon
|
||||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(g_pCompositor->m_pLastMonitor->ID);
|
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(g_pCompositor->m_pLastMonitor->ID);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CKeybindManager::exitHyprland(std::string argz) {
|
||||||
|
g_pCompositor->cleanupExit();
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CKeybindManager::moveCurrentWorkspaceToMonitor(std::string args) {
|
||||||
|
if (!isNumber(args) && !isDirection(args)) {
|
||||||
|
Debug::log(ERR, "moveCurrentWorkspaceToMonitor arg not a number or direction!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto PMONITOR = isDirection(args) ? g_pCompositor->getMonitorInDirection(args[0]) : g_pCompositor->getMonitorFromID(std::stoi(args));
|
||||||
|
|
||||||
|
if (!PMONITOR) {
|
||||||
|
Debug::log(ERR, "Ignoring moveCurrentWorkspaceToMonitor: monitor doesnt exist");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the current workspace
|
||||||
|
const auto PCURRENTWORKSPACE = g_pCompositor->getWorkspaceByID(g_pCompositor->m_pLastMonitor->activeWorkspace);
|
||||||
|
|
||||||
|
if (!PCURRENTWORKSPACE)
|
||||||
|
return;
|
||||||
|
|
||||||
|
g_pCompositor->moveWorkspaceToMonitor(PCURRENTWORKSPACE, PMONITOR);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CKeybindManager::moveWorkspaceToMonitor(std::string args) {
|
||||||
|
if (args.find_first_of(' ') == std::string::npos)
|
||||||
|
return;
|
||||||
|
|
||||||
|
std::string workspace = args.substr(0, args.find_first_of(' '));
|
||||||
|
std::string monitor = args.substr(args.find_first_of(' ') + 1);
|
||||||
|
|
||||||
|
if (!isNumber(monitor) && !isDirection(monitor)) {
|
||||||
|
Debug::log(ERR, "moveWorkspaceToMonitor monitor arg not a number or direction!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto PMONITOR = isDirection(monitor) ? g_pCompositor->getMonitorInDirection(monitor[0]) : g_pCompositor->getMonitorFromID(std::stoi(monitor));
|
||||||
|
|
||||||
|
if (!PMONITOR){
|
||||||
|
Debug::log(ERR, "Ignoring moveWorkspaceToMonitor: monitor doesnt exist");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string workspaceName;
|
||||||
|
const int WORKSPACEID = getWorkspaceIDFromString(workspace, workspaceName);
|
||||||
|
|
||||||
|
if (WORKSPACEID == INT_MAX) {
|
||||||
|
Debug::log(ERR, "moveWorkspaceToMonitor invalid workspace!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(WORKSPACEID);
|
||||||
|
|
||||||
|
if (!PWORKSPACE) {
|
||||||
|
Debug::log(ERR, "moveWorkspaceToMonitor workspace doesn't exist!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_pCompositor->moveWorkspaceToMonitor(PWORKSPACE, PMONITOR);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CKeybindManager::toggleSpecialWorkspace(std::string args) {
|
||||||
|
|
||||||
|
if (g_pCompositor->getWindowsOnWorkspace(SPECIAL_WORKSPACE_ID) == 0) {
|
||||||
|
Debug::log(LOG, "Can't open empty special workspace!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool open = false;
|
||||||
|
|
||||||
|
for (auto& m : g_pCompositor->m_lMonitors) {
|
||||||
|
if (m.specialWorkspaceOpen) {
|
||||||
|
open = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (open)
|
||||||
|
Debug::log(LOG, "Toggling special workspace to closed");
|
||||||
|
else
|
||||||
|
Debug::log(LOG, "Toggling special workspace to open");
|
||||||
|
|
||||||
|
if (open) {
|
||||||
|
for (auto& m : g_pCompositor->m_lMonitors) {
|
||||||
|
if (m.specialWorkspaceOpen != !open) {
|
||||||
|
m.specialWorkspaceOpen = !open;
|
||||||
|
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m.ID);
|
||||||
|
|
||||||
|
g_pCompositor->getWorkspaceByID(SPECIAL_WORKSPACE_ID)->startAnim(false, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
g_pCompositor->m_pLastMonitor->specialWorkspaceOpen = true;
|
||||||
|
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(g_pCompositor->m_pLastMonitor->ID);
|
||||||
|
|
||||||
|
g_pCompositor->getWorkspaceByID(SPECIAL_WORKSPACE_ID)->startAnim(true, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_pInputManager->refocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CKeybindManager::forceRendererReload(std::string args) {
|
||||||
|
for (auto& m : g_pCompositor->m_lMonitors) {
|
||||||
|
auto rule = g_pConfigManager->getMonitorRuleFor(m.szName);
|
||||||
|
g_pHyprRenderer->applyMonitorRule(&m, &rule, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CKeybindManager::resizeActive(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 (!isNumber(x) || !isNumber(y)) {
|
||||||
|
Debug::log(ERR, "resizeTiledWindow: args not numbers");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const int X = std::stoi(x);
|
||||||
|
const int Y = std::stoi(y);
|
||||||
|
|
||||||
|
g_pLayoutManager->getCurrentLayout()->resizeActiveWindow(Vector2D(X, Y));
|
||||||
}
|
}
|
@@ -50,6 +50,14 @@ private:
|
|||||||
static void toggleSplit(std::string);
|
static void toggleSplit(std::string);
|
||||||
static void moveCursorToCorner(std::string);
|
static void moveCursorToCorner(std::string);
|
||||||
static void workspaceOpt(std::string);
|
static void workspaceOpt(std::string);
|
||||||
|
static void exitHyprland(std::string);
|
||||||
|
static void moveCurrentWorkspaceToMonitor(std::string);
|
||||||
|
static void moveWorkspaceToMonitor(std::string);
|
||||||
|
static void toggleSpecialWorkspace(std::string);
|
||||||
|
static void forceRendererReload(std::string);
|
||||||
|
static void resizeActive(std::string);
|
||||||
|
|
||||||
|
friend class CCompositor;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline std::unique_ptr<CKeybindManager> g_pKeybindManager;
|
inline std::unique_ptr<CKeybindManager> g_pKeybindManager;
|
@@ -94,6 +94,9 @@ std::string CHyprXWaylandManager::getAppIDClass(CWindow* pWindow) {
|
|||||||
try {
|
try {
|
||||||
if (pWindow->m_bIsX11) {
|
if (pWindow->m_bIsX11) {
|
||||||
if (pWindow->m_uSurface.xwayland) {
|
if (pWindow->m_uSurface.xwayland) {
|
||||||
|
if (!pWindow->m_bMappedX11 || !pWindow->m_bIsMapped)
|
||||||
|
return "unmanaged X11";
|
||||||
|
|
||||||
return std::string(pWindow->m_uSurface.xwayland->_class);
|
return std::string(pWindow->m_uSurface.xwayland->_class);
|
||||||
}
|
}
|
||||||
} else if (pWindow->m_uSurface.xdg) {
|
} else if (pWindow->m_uSurface.xdg) {
|
||||||
@@ -121,8 +124,14 @@ 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 // vvvvv I don't know if this is fucking correct, but the fucking idea of putting shadows into a window's surface is borderline criminal.
|
else {
|
||||||
wlr_xdg_toplevel_set_size(pWindow->m_uSurface.xdg->toplevel, size.x - pWindow->m_uSurface.xdg->current.geometry.x * 2, size.y - pWindow->m_uSurface.xdg->current.geometry.y * 2);
|
// I don't know if this is fucking correct, but the fucking idea of putting shadows into a window's surface is borderline criminal.
|
||||||
|
|
||||||
|
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) {
|
||||||
@@ -217,5 +226,8 @@ void CHyprXWaylandManager::setWindowFullscreen(CWindow* pWindow, bool fullscreen
|
|||||||
wlr_xdg_toplevel_set_fullscreen(pWindow->m_uSurface.xdg->toplevel, fullscreen);
|
wlr_xdg_toplevel_set_fullscreen(pWindow->m_uSurface.xdg->toplevel, fullscreen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (pWindow->m_phForeignToplevel)
|
||||||
|
wlr_foreign_toplevel_handle_v1_set_fullscreen(pWindow->m_phForeignToplevel, fullscreen);
|
||||||
|
|
||||||
g_pEventManager->postEvent(SHyprIPCEvent("fullscreen", std::to_string((int)fullscreen)));
|
g_pEventManager->postEvent(SHyprIPCEvent("fullscreen", std::to_string((int)fullscreen)));
|
||||||
}
|
}
|
@@ -166,13 +166,17 @@ void CHyprOpenGLImpl::end() {
|
|||||||
// end the render, copy the data to the WLR framebuffer
|
// end the render, copy the data to the WLR framebuffer
|
||||||
if (!m_bFakeFrame) {
|
if (!m_bFakeFrame) {
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, m_iWLROutputFb);
|
glBindFramebuffer(GL_FRAMEBUFFER, m_iWLROutputFb);
|
||||||
wlr_box monbox = {0, 0, m_RenderData.pMonitor->vecPixelSize.x, m_RenderData.pMonitor->vecPixelSize.y};
|
wlr_box monbox = {0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y};
|
||||||
|
|
||||||
pixman_region32_copy(m_RenderData.pDamage, &m_rOriginalDamageRegion);
|
pixman_region32_copy(m_RenderData.pDamage, &m_rOriginalDamageRegion);
|
||||||
|
|
||||||
clear(CColor(11, 11, 11, 255));
|
clear(CColor(11, 11, 11, 255));
|
||||||
|
|
||||||
|
m_bEndFrame = true;
|
||||||
|
|
||||||
renderTexture(m_mMonitorRenderResources[m_RenderData.pMonitor].primaryFB.m_cTex, &monbox, 255.f, 0);
|
renderTexture(m_mMonitorRenderResources[m_RenderData.pMonitor].primaryFB.m_cTex, &monbox, 255.f, 0);
|
||||||
|
|
||||||
|
m_bEndFrame = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// reset our data
|
// reset our data
|
||||||
@@ -205,7 +209,15 @@ void CHyprOpenGLImpl::scissor(const wlr_box* pBox) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
glScissor(pBox->x, pBox->y, pBox->width, pBox->height);
|
wlr_box newBox = *pBox;
|
||||||
|
|
||||||
|
int w, h;
|
||||||
|
wlr_output_transformed_resolution(m_RenderData.pMonitor->output, &w, &h);
|
||||||
|
|
||||||
|
const auto TR = wlr_output_transform_invert(m_RenderData.pMonitor->transform);
|
||||||
|
wlr_box_transform(&newBox, &newBox, TR, w, h);
|
||||||
|
|
||||||
|
glScissor(newBox.x, newBox.y, newBox.width, newBox.height);
|
||||||
glEnable(GL_SCISSOR_TEST);
|
glEnable(GL_SCISSOR_TEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -217,8 +229,9 @@ void CHyprOpenGLImpl::scissor(const pixman_box32* pBox) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
glScissor(pBox->x1, pBox->y1, pBox->x2 - pBox->x1, pBox->y2 - pBox->y1);
|
wlr_box newBox = {pBox->x1, pBox->y1, pBox->x2 - pBox->x1, pBox->y2 - pBox->y1};
|
||||||
glEnable(GL_SCISSOR_TEST);
|
|
||||||
|
scissor(&newBox);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CHyprOpenGLImpl::scissor(const int x, const int y, const int w, const int h) {
|
void CHyprOpenGLImpl::scissor(const int x, const int y, const int w, const int h) {
|
||||||
@@ -231,7 +244,7 @@ void CHyprOpenGLImpl::renderRect(wlr_box* box, const CColor& col, int round) {
|
|||||||
RASSERT(m_RenderData.pMonitor, "Tried to render rect without begin()!");
|
RASSERT(m_RenderData.pMonitor, "Tried to render rect without begin()!");
|
||||||
|
|
||||||
float matrix[9];
|
float matrix[9];
|
||||||
wlr_matrix_project_box(matrix, box, WL_OUTPUT_TRANSFORM_NORMAL, 0, m_RenderData.pMonitor->output->transform_matrix); // TODO: write own, don't use WLR here
|
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];
|
float glMatrix[9];
|
||||||
wlr_matrix_multiply(glMatrix, m_RenderData.projection, matrix);
|
wlr_matrix_multiply(glMatrix, m_RenderData.projection, matrix);
|
||||||
@@ -256,6 +269,7 @@ void CHyprOpenGLImpl::renderRect(wlr_box* box, const CColor& col, int round) {
|
|||||||
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));
|
||||||
|
|
||||||
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);
|
||||||
@@ -291,12 +305,12 @@ void CHyprOpenGLImpl::renderTexture(const CTexture& tex, wlr_box* pBox, float al
|
|||||||
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) {
|
void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_box* pBox, float alpha, pixman_region32_t* damage, int round, bool discardOpaque, bool border, bool noAA) {
|
||||||
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!");
|
||||||
|
|
||||||
// get transform
|
// get transform
|
||||||
const auto TRANSFORM = wlr_output_transform_invert(WL_OUTPUT_TRANSFORM_NORMAL);
|
const auto TRANSFORM = wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform);
|
||||||
float matrix[9];
|
float matrix[9];
|
||||||
wlr_matrix_project_box(matrix, pBox, TRANSFORM, 0, m_RenderData.pMonitor->output->transform_matrix);
|
wlr_matrix_project_box(matrix, pBox, TRANSFORM, 0, m_RenderData.pMonitor->output->transform_matrix);
|
||||||
|
|
||||||
@@ -349,6 +363,7 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_b
|
|||||||
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));
|
||||||
|
|
||||||
glVertexAttribPointer(shader->posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
|
glVertexAttribPointer(shader->posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
|
||||||
glVertexAttribPointer(shader->texAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
|
glVertexAttribPointer(shader->texAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
|
||||||
@@ -534,7 +549,7 @@ void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, wlr_box* pBox,
|
|||||||
pixman_region32_t inverseOpaque;
|
pixman_region32_t inverseOpaque;
|
||||||
pixman_region32_init(&inverseOpaque);
|
pixman_region32_init(&inverseOpaque);
|
||||||
if (a == 255.f) {
|
if (a == 255.f) {
|
||||||
pixman_box32_t monbox = {0, 0, m_RenderData.pMonitor->vecPixelSize.x, m_RenderData.pMonitor->vecPixelSize.y};
|
pixman_box32_t monbox = {0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y};
|
||||||
pixman_region32_copy(&inverseOpaque, &pSurface->current.opaque);
|
pixman_region32_copy(&inverseOpaque, &pSurface->current.opaque);
|
||||||
pixman_region32_translate(&inverseOpaque, pBox->x, pBox->y);
|
pixman_region32_translate(&inverseOpaque, pBox->x, pBox->y);
|
||||||
pixman_region32_inverse(&inverseOpaque, &inverseOpaque, &monbox);
|
pixman_region32_inverse(&inverseOpaque, &inverseOpaque, &monbox);
|
||||||
@@ -572,11 +587,11 @@ void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, wlr_box* pBox,
|
|||||||
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
|
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
|
||||||
|
|
||||||
// stencil done. Render everything.
|
// stencil done. Render everything.
|
||||||
wlr_box MONITORBOX = {0, 0, m_RenderData.pMonitor->vecPixelSize.x, m_RenderData.pMonitor->vecPixelSize.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, a, &damage);
|
renderTextureInternalWithDamage(POUTFB->m_cTex, &MONITORBOX, g_pConfigManager->getInt("decoration:blur_ignore_opacity") ? 255.f : a, &damage);
|
||||||
|
|
||||||
// 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);
|
||||||
@@ -585,7 +600,7 @@ void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, wlr_box* pBox,
|
|||||||
glStencilFunc(GL_ALWAYS, 1, -1);
|
glStencilFunc(GL_ALWAYS, 1, -1);
|
||||||
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
|
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
|
||||||
|
|
||||||
renderTextureInternalWithDamage(tex, pBox, a, &damage, round);
|
renderTextureInternalWithDamage(tex, pBox, a, &damage, round, false, false, true);
|
||||||
|
|
||||||
// then stop
|
// then stop
|
||||||
glStencilFunc(GL_EQUAL, 1, -1);
|
glStencilFunc(GL_EQUAL, 1, -1);
|
||||||
@@ -624,7 +639,7 @@ void CHyprOpenGLImpl::renderBorder(wlr_box* box, const CColor& col, int thick, i
|
|||||||
box->width += 2 * thick;
|
box->width += 2 * thick;
|
||||||
box->height += 2 * thick;
|
box->height += 2 * thick;
|
||||||
|
|
||||||
round += thick; // cuz yeah
|
round += thick * m_RenderData.pMonitor->scale; // cuz yeah
|
||||||
|
|
||||||
// only draw on non-stencild.
|
// only draw on non-stencild.
|
||||||
glStencilFunc(GL_NOTEQUAL, 1, -1);
|
glStencilFunc(GL_NOTEQUAL, 1, -1);
|
||||||
@@ -756,7 +771,14 @@ void CHyprOpenGLImpl::renderSnapshot(CWindow** pWindow) {
|
|||||||
|
|
||||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID);
|
const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID);
|
||||||
|
|
||||||
wlr_box windowBox = {0, 0, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y};
|
wlr_box windowBox;
|
||||||
|
// some mafs to figure out the correct box
|
||||||
|
Vector2D scaleXY = Vector2D((PWINDOW->m_vRealSize.vec().x / PWINDOW->m_vOriginalClosedSize.x), (PWINDOW->m_vRealSize.vec().y / PWINDOW->m_vOriginalClosedSize.y));
|
||||||
|
|
||||||
|
windowBox.width = PMONITOR->vecPixelSize.x * scaleXY.x;
|
||||||
|
windowBox.height = PMONITOR->vecPixelSize.y * scaleXY.y;
|
||||||
|
windowBox.x = (PWINDOW->m_vRealPosition.vec().x - PMONITOR->vecPosition.x) - ((PWINDOW->m_vOriginalClosedPos.x - PMONITOR->vecPosition.x) * scaleXY.x);
|
||||||
|
windowBox.y = (PWINDOW->m_vRealPosition.vec().y - PMONITOR->vecPosition.y) - ((PWINDOW->m_vOriginalClosedPos.y - PMONITOR->vecPosition.y) * scaleXY.y);
|
||||||
|
|
||||||
pixman_region32_t fakeDamage;
|
pixman_region32_t fakeDamage;
|
||||||
pixman_region32_init_rect(&fakeDamage, 0, 0, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y);
|
pixman_region32_init_rect(&fakeDamage, 0, 0, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y);
|
||||||
@@ -810,10 +832,10 @@ void CHyprOpenGLImpl::createBGTextureForMonitor(SMonitor* pMonitor) {
|
|||||||
// get the adequate tex
|
// get the adequate tex
|
||||||
std::string texPath = "/usr/share/hyprland/wall_";
|
std::string texPath = "/usr/share/hyprland/wall_";
|
||||||
Vector2D textureSize;
|
Vector2D textureSize;
|
||||||
if (pMonitor->vecSize.x > 7000) {
|
if (pMonitor->vecTransformedSize.x > 7000) {
|
||||||
textureSize = Vector2D(7680, 4320);
|
textureSize = Vector2D(7680, 4320);
|
||||||
texPath += "8K.png";
|
texPath += "8K.png";
|
||||||
} else if (pMonitor->vecSize.x > 3000) {
|
} else if (pMonitor->vecTransformedSize.x > 3000) {
|
||||||
textureSize = Vector2D(3840, 2160);
|
textureSize = Vector2D(3840, 2160);
|
||||||
texPath += "4K.png";
|
texPath += "4K.png";
|
||||||
} else {
|
} else {
|
||||||
@@ -846,7 +868,7 @@ void CHyprOpenGLImpl::createBGTextureForMonitor(SMonitor* pMonitor) {
|
|||||||
void CHyprOpenGLImpl::clearWithTex() {
|
void CHyprOpenGLImpl::clearWithTex() {
|
||||||
RASSERT(m_RenderData.pMonitor, "Tried to render BGtex without begin()!");
|
RASSERT(m_RenderData.pMonitor, "Tried to render BGtex without begin()!");
|
||||||
|
|
||||||
wlr_box box = {0, 0, m_RenderData.pMonitor->vecPixelSize.x, m_RenderData.pMonitor->vecPixelSize.y};
|
wlr_box box = {0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y};
|
||||||
|
|
||||||
renderTexture(m_mMonitorBGTextures[m_RenderData.pMonitor], &box, 255, 0);
|
renderTexture(m_mMonitorBGTextures[m_RenderData.pMonitor], &box, 255, 0);
|
||||||
}
|
}
|
||||||
|
@@ -92,6 +92,7 @@ private:
|
|||||||
std::string m_szExtensions;
|
std::string m_szExtensions;
|
||||||
|
|
||||||
bool m_bFakeFrame = false;
|
bool m_bFakeFrame = false;
|
||||||
|
bool m_bEndFrame = false;
|
||||||
|
|
||||||
// Shaders
|
// Shaders
|
||||||
SQuad m_shQUAD;
|
SQuad m_shQUAD;
|
||||||
@@ -109,7 +110,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);
|
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 renderBorder(wlr_box*, const CColor&, int thick = 1, int round = 0);
|
void renderBorder(wlr_box*, const CColor&, int thick = 1, int round = 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -19,18 +19,20 @@ 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;
|
||||||
|
|
||||||
if (RDATA->surface && surface == RDATA->surface)
|
if (RDATA->surface && surface == RDATA->surface)
|
||||||
g_pHyprOpenGL->renderTextureWithBlur(TEXTURE, &windowBox, RDATA->fadeAlpha * RDATA->alpha, surface, RDATA->dontRound ? 0 : g_pConfigManager->getInt("decoration:rounding"), RDATA->decorate);
|
g_pHyprOpenGL->renderTextureWithBlur(TEXTURE, &windowBox, RDATA->fadeAlpha * RDATA->alpha, surface, rounding, RDATA->decorate);
|
||||||
else
|
else
|
||||||
g_pHyprOpenGL->renderTexture(TEXTURE, &windowBox, RDATA->fadeAlpha * RDATA->alpha, RDATA->dontRound ? 0 : g_pConfigManager->getInt("decoration:rounding"), false, false);
|
g_pHyprOpenGL->renderTexture(TEXTURE, &windowBox, RDATA->fadeAlpha * RDATA->alpha, rounding, false, false);
|
||||||
|
|
||||||
wlr_surface_send_frame_done(surface, RDATA->when);
|
wlr_surface_send_frame_done(surface, RDATA->when);
|
||||||
|
|
||||||
wlr_presentation_surface_sampled_on_output(g_pCompositor->m_sWLRPresentation, surface, RDATA->output);
|
wlr_presentation_surface_sampled_on_output(g_pCompositor->m_sWLRPresentation, surface, RDATA->output);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool shouldRenderWindow(CWindow* pWindow, SMonitor* pMonitor) {
|
bool CHyprRenderer::shouldRenderWindow(CWindow* pWindow, SMonitor* pMonitor) {
|
||||||
wlr_box geometry = {pWindow->m_vRealPosition.vec().x, pWindow->m_vRealPosition.vec().y, pWindow->m_vRealSize.vec().x, pWindow->m_vRealSize.vec().y};
|
wlr_box geometry = pWindow->getFullWindowBoundingBox();
|
||||||
|
|
||||||
if (!wlr_output_layout_intersects(g_pCompositor->m_sWLROutputLayout, pMonitor->output, &geometry))
|
if (!wlr_output_layout_intersects(g_pCompositor->m_sWLROutputLayout, pMonitor->output, &geometry))
|
||||||
return false;
|
return false;
|
||||||
@@ -44,6 +46,30 @@ bool shouldRenderWindow(CWindow* pWindow, SMonitor* pMonitor) {
|
|||||||
if (g_pCompositor->isWorkspaceVisible(pWindow->m_iWorkspaceID) || (PWORKSPACE && PWORKSPACE->m_iMonitorID == pMonitor->ID && (PWORKSPACE->m_vRenderOffset.isBeingAnimated() || PWORKSPACE->m_fAlpha.isBeingAnimated())))
|
if (g_pCompositor->isWorkspaceVisible(pWindow->m_iWorkspaceID) || (PWORKSPACE && PWORKSPACE->m_iMonitorID == pMonitor->ID && (PWORKSPACE->m_vRenderOffset.isBeingAnimated() || PWORKSPACE->m_fAlpha.isBeingAnimated())))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
if (pMonitor->specialWorkspaceOpen && pWindow->m_iWorkspaceID == SPECIAL_WORKSPACE_ID)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CHyprRenderer::shouldRenderWindow(CWindow* pWindow) {
|
||||||
|
|
||||||
|
if (!g_pCompositor->windowValidMapped(pWindow))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID);
|
||||||
|
|
||||||
|
if (g_pCompositor->isWorkspaceVisible(pWindow->m_iWorkspaceID))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
for (auto& m : g_pCompositor->m_lMonitors) {
|
||||||
|
if (PWORKSPACE && PWORKSPACE->m_iMonitorID == m.ID && (PWORKSPACE->m_vRenderOffset.isBeingAnimated() || PWORKSPACE->m_fAlpha.isBeingAnimated()))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (m.specialWorkspaceOpen && pWindow->m_iWorkspaceID == SPECIAL_WORKSPACE_ID)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,7 +81,7 @@ void CHyprRenderer::renderWorkspaceWithFullscreenWindow(SMonitor* pMonitor, CWor
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
// found it!
|
// found it!
|
||||||
renderWindow(&w, pMonitor, time, false);
|
renderWindow(&w, pMonitor, time, pWorkspace->m_efFullscreenMode != FULLSCREEN_FULL);
|
||||||
|
|
||||||
pWorkspaceWindow = &w;
|
pWorkspaceWindow = &w;
|
||||||
}
|
}
|
||||||
@@ -68,7 +94,29 @@ void CHyprRenderer::renderWorkspaceWithFullscreenWindow(SMonitor* pMonitor, CWor
|
|||||||
renderWindow(&w, pMonitor, time, true);
|
renderWindow(&w, pMonitor, time, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// and then special windows
|
||||||
|
for (auto& w : g_pCompositor->m_lWindows) {
|
||||||
|
if (!g_pCompositor->windowValidMapped(&w) && !w.m_bFadingOut)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (w.m_iWorkspaceID != SPECIAL_WORKSPACE_ID)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!shouldRenderWindow(&w, pMonitor))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// render the bad boy
|
||||||
|
renderWindow(&w, pMonitor, time, true);
|
||||||
|
}
|
||||||
|
|
||||||
// and the overlay layers
|
// and the overlay layers
|
||||||
|
if (pWorkspace->m_efFullscreenMode != FULLSCREEN_FULL) {
|
||||||
|
// on non-full we draw the bar and shit
|
||||||
|
for (auto& ls : pMonitor->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_TOP]) {
|
||||||
|
renderLayer(ls, pMonitor, time);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (auto& ls : pMonitor->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]) {
|
for (auto& ls : pMonitor->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]) {
|
||||||
renderLayer(ls, pMonitor, time);
|
renderLayer(ls, pMonitor, time);
|
||||||
}
|
}
|
||||||
@@ -85,7 +133,8 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, SMonitor* pMonitor, timespec*
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (pWindow->m_bFadingOut) {
|
if (pWindow->m_bFadingOut) {
|
||||||
g_pHyprOpenGL->renderSnapshot(&pWindow);
|
if (pMonitor->ID == pWindow->m_iMonitorID) // TODO: fix this
|
||||||
|
g_pHyprOpenGL->renderSnapshot(&pWindow);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,16 +144,24 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, SMonitor* pMonitor, timespec*
|
|||||||
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,
|
||||||
renderdata.h = std::clamp(pWindow->m_vRealSize.vec().y, (double)5, (double)1337420); // otherwise we'll have issues later with invalid boxes
|
renderdata.h = std::clamp(pWindow->m_vRealSize.vec().y, (double)5, (double)1337420); // otherwise we'll have issues later with invalid boxes
|
||||||
renderdata.dontRound = pWindow->m_bIsFullscreen;
|
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;
|
||||||
|
renderdata.rounding = pWindow->m_sAdditionalConfigData.rounding;
|
||||||
|
|
||||||
// apply window special data
|
// apply window special data
|
||||||
renderdata.alpha *= pWindow->m_sSpecialRenderData.alpha;
|
if (pWindow->m_sSpecialRenderData.alphaInactive == -1)
|
||||||
|
renderdata.alpha *= pWindow->m_sSpecialRenderData.alpha;
|
||||||
|
else
|
||||||
|
renderdata.alpha *= pWindow == g_pCompositor->m_pLastWindow ? pWindow->m_sSpecialRenderData.alpha : pWindow->m_sSpecialRenderData.alphaInactive;
|
||||||
|
|
||||||
g_pHyprOpenGL->m_pCurrentWindow = pWindow;
|
g_pHyprOpenGL->m_pCurrentWindow = pWindow;
|
||||||
|
|
||||||
|
// render window decorations first
|
||||||
|
for (auto& wd : pWindow->m_dWindowDecorations)
|
||||||
|
wd->draw(pMonitor);
|
||||||
|
|
||||||
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) {
|
if (pWindow->m_bIsX11) {
|
||||||
@@ -161,7 +218,10 @@ void CHyprRenderer::renderAllClientsForMonitor(const int& ID, timespec* time) {
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (w.m_bIsFloating)
|
if (w.m_bIsFloating)
|
||||||
continue; // floating are in second pass
|
continue; // floating are in the second pass
|
||||||
|
|
||||||
|
if (w.m_iWorkspaceID == SPECIAL_WORKSPACE_ID)
|
||||||
|
continue; // special are in the third pass
|
||||||
|
|
||||||
if (!shouldRenderWindow(&w, PMONITOR))
|
if (!shouldRenderWindow(&w, PMONITOR))
|
||||||
continue;
|
continue;
|
||||||
@@ -178,6 +238,24 @@ void CHyprRenderer::renderAllClientsForMonitor(const int& ID, timespec* time) {
|
|||||||
if (!w.m_bIsFloating)
|
if (!w.m_bIsFloating)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (w.m_iWorkspaceID == SPECIAL_WORKSPACE_ID)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!shouldRenderWindow(&w, PMONITOR))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// render the bad boy
|
||||||
|
renderWindow(&w, PMONITOR, time, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// and then special
|
||||||
|
for (auto& w : g_pCompositor->m_lWindows) {
|
||||||
|
if (!g_pCompositor->windowValidMapped(&w) && !w.m_bFadingOut)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (w.m_iWorkspaceID != SPECIAL_WORKSPACE_ID)
|
||||||
|
continue;
|
||||||
|
|
||||||
if (!shouldRenderWindow(&w, PMONITOR))
|
if (!shouldRenderWindow(&w, PMONITOR))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@@ -194,10 +272,6 @@ void CHyprRenderer::renderAllClientsForMonitor(const int& ID, timespec* time) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
renderDragIcon(PMONITOR, time);
|
renderDragIcon(PMONITOR, time);
|
||||||
|
|
||||||
// if correct monitor draw hyprerror
|
|
||||||
if (PMONITOR == &g_pCompositor->m_lMonitors.front())
|
|
||||||
g_pHyprError->draw();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CHyprRenderer::outputMgrApplyTest(wlr_output_configuration_v1* config, bool test) {
|
void CHyprRenderer::outputMgrApplyTest(wlr_output_configuration_v1* config, bool test) {
|
||||||
@@ -548,7 +622,7 @@ void CHyprRenderer::applyMonitorRule(SMonitor* pMonitor, SMonitorRule* pMonitorR
|
|||||||
Debug::log(LOG, "Applying monitor rule for %s", pMonitor->szName.c_str());
|
Debug::log(LOG, "Applying monitor rule for %s", pMonitor->szName.c_str());
|
||||||
|
|
||||||
// Check if the rule isn't already applied
|
// Check if the rule isn't already applied
|
||||||
if (!force && DELTALESSTHAN(pMonitor->vecPixelSize.x, pMonitorRule->resolution.x, 1) && DELTALESSTHAN(pMonitor->vecPixelSize.y, pMonitorRule->resolution.y, 1) && DELTALESSTHAN(pMonitor->refreshRate, pMonitorRule->refreshRate, 1) && pMonitor->scale == pMonitorRule->scale && DELTALESSTHAN(pMonitor->vecPosition.x, pMonitorRule->offset.x, 1) && DELTALESSTHAN(pMonitor->vecPosition.y, pMonitorRule->offset.y, 1)) {
|
if (!force && DELTALESSTHAN(pMonitor->vecPixelSize.x, pMonitorRule->resolution.x, 1) && DELTALESSTHAN(pMonitor->vecPixelSize.y, pMonitorRule->resolution.y, 1) && DELTALESSTHAN(pMonitor->refreshRate, pMonitorRule->refreshRate, 1) && pMonitor->scale == pMonitorRule->scale && DELTALESSTHAN(pMonitor->vecPosition.x, pMonitorRule->offset.x, 1) && DELTALESSTHAN(pMonitor->vecPosition.y, pMonitorRule->offset.y, 1) && pMonitor->transform == pMonitorRule->transform) {
|
||||||
Debug::log(LOG, "Not applying a new rule to %s because it's already applied!", pMonitor->szName.c_str());
|
Debug::log(LOG, "Not applying a new rule to %s because it's already applied!", pMonitor->szName.c_str());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -612,8 +686,10 @@ void CHyprRenderer::applyMonitorRule(SMonitor* pMonitor, SMonitorRule* pMonitorR
|
|||||||
pMonitor->vecSize = pMonitorRule->resolution;
|
pMonitor->vecSize = pMonitorRule->resolution;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wlr_output_set_transform(pMonitor->output, pMonitorRule->transform);
|
||||||
|
pMonitor->transform = pMonitorRule->transform;
|
||||||
|
|
||||||
pMonitor->vecPixelSize = pMonitor->vecSize;
|
pMonitor->vecPixelSize = pMonitor->vecSize;
|
||||||
pMonitor->vecSize = (pMonitor->vecSize / pMonitor->scale).floor();
|
|
||||||
|
|
||||||
// update renderer
|
// update renderer
|
||||||
g_pHyprOpenGL->destroyMonitorResources(pMonitor);
|
g_pHyprOpenGL->destroyMonitorResources(pMonitor);
|
||||||
@@ -623,6 +699,11 @@ void CHyprRenderer::applyMonitorRule(SMonitor* pMonitor, SMonitorRule* pMonitorR
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int x, y;
|
||||||
|
wlr_output_transformed_resolution(pMonitor->output, &x, &y);
|
||||||
|
pMonitor->vecSize = (Vector2D(x, y) / pMonitor->scale).floor();
|
||||||
|
pMonitor->vecTransformedSize = Vector2D(x,y);
|
||||||
|
|
||||||
wlr_output_layout_add(g_pCompositor->m_sWLROutputLayout, pMonitor->output, (int)pMonitorRule->offset.x, (int)pMonitorRule->offset.y);
|
wlr_output_layout_add(g_pCompositor->m_sWLROutputLayout, pMonitor->output, (int)pMonitorRule->offset.x, (int)pMonitorRule->offset.y);
|
||||||
|
|
||||||
//wlr_output_damage_add_whole(pMonitor->damage);
|
//wlr_output_damage_add_whole(pMonitor->damage);
|
||||||
@@ -636,5 +717,5 @@ void CHyprRenderer::applyMonitorRule(SMonitor* pMonitor, SMonitorRule* pMonitorR
|
|||||||
arrangeLayersForMonitor(pMonitor->ID);
|
arrangeLayersForMonitor(pMonitor->ID);
|
||||||
|
|
||||||
// frame skip
|
// frame skip
|
||||||
pMonitor->needsFrameSkip = true;
|
pMonitor->framesToSkip = 1;
|
||||||
}
|
}
|
||||||
|
@@ -29,6 +29,8 @@ public:
|
|||||||
void damageBox(const int& x, const int& y, const int& w, const int& h);
|
void damageBox(const int& x, const int& y, const int& w, const int& h);
|
||||||
void damageMonitor(SMonitor*);
|
void damageMonitor(SMonitor*);
|
||||||
void applyMonitorRule(SMonitor*, SMonitorRule*, bool force = false);
|
void applyMonitorRule(SMonitor*, SMonitorRule*, bool force = false);
|
||||||
|
bool shouldRenderWindow(CWindow*, SMonitor*);
|
||||||
|
bool shouldRenderWindow(CWindow*);
|
||||||
|
|
||||||
DAMAGETRACKINGMODES damageTrackingModeFromStr(const std::string&);
|
DAMAGETRACKINGMODES damageTrackingModeFromStr(const std::string&);
|
||||||
|
|
||||||
|
@@ -2,6 +2,147 @@
|
|||||||
|
|
||||||
#include <string>
|
#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"#(
|
inline const std::string QUADVERTSRC = R"#(
|
||||||
uniform mat3 proj;
|
uniform mat3 proj;
|
||||||
uniform vec4 color;
|
uniform vec4 color;
|
||||||
@@ -26,6 +167,9 @@ uniform vec2 bottomRight;
|
|||||||
uniform vec2 fullSize;
|
uniform vec2 fullSize;
|
||||||
uniform float radius;
|
uniform float radius;
|
||||||
|
|
||||||
|
uniform int primitiveMultisample;
|
||||||
|
uniform int ignoreCorners;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
if (radius == 0.0) {
|
if (radius == 0.0) {
|
||||||
gl_FragColor = v_color;
|
gl_FragColor = v_color;
|
||||||
@@ -34,38 +178,7 @@ void main() {
|
|||||||
|
|
||||||
vec2 pixCoord = fullSize * v_texcoord;
|
vec2 pixCoord = fullSize * v_texcoord;
|
||||||
|
|
||||||
if (pixCoord[0] < topLeft[0]) {
|
)#" + ROUNDED_SHADER_FUNC("v_color") + R"#(
|
||||||
// we're close left
|
|
||||||
if (pixCoord[1] < topLeft[1]) {
|
|
||||||
// top
|
|
||||||
if (distance(topLeft, pixCoord) > radius) {
|
|
||||||
discard;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else if (pixCoord[1] > bottomRight[1]) {
|
|
||||||
// bottom
|
|
||||||
if (distance(vec2(topLeft[0], bottomRight[1]), pixCoord) > radius) {
|
|
||||||
discard;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (pixCoord[0] > bottomRight[0]) {
|
|
||||||
// we're close right
|
|
||||||
if (pixCoord[1] < topLeft[1]) {
|
|
||||||
// top
|
|
||||||
if (distance(vec2(bottomRight[0], topLeft[1]), pixCoord) > radius) {
|
|
||||||
discard;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else if (pixCoord[1] > bottomRight[1]) {
|
|
||||||
// bottom
|
|
||||||
if (distance(bottomRight, pixCoord) > radius) {
|
|
||||||
discard;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
gl_FragColor = v_color;
|
gl_FragColor = v_color;
|
||||||
})#";
|
})#";
|
||||||
@@ -94,6 +207,9 @@ uniform float radius;
|
|||||||
|
|
||||||
uniform int discardOpaque;
|
uniform int discardOpaque;
|
||||||
|
|
||||||
|
uniform int primitiveMultisample;
|
||||||
|
uniform int ignoreCorners;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
|
|
||||||
vec4 pixColor = texture2D(tex, v_texcoord);
|
vec4 pixColor = texture2D(tex, v_texcoord);
|
||||||
@@ -105,38 +221,8 @@ void main() {
|
|||||||
|
|
||||||
vec2 pixCoord = fullSize * v_texcoord;
|
vec2 pixCoord = fullSize * v_texcoord;
|
||||||
|
|
||||||
if (pixCoord[0] < topLeft[0]) {
|
)#" + ROUNDED_SHADER_FUNC("pixColor") +
|
||||||
// we're close left
|
R"#(
|
||||||
if (pixCoord[1] < topLeft[1]) {
|
|
||||||
// top
|
|
||||||
if (distance(topLeft, pixCoord) > radius) {
|
|
||||||
discard;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else if (pixCoord[1] > bottomRight[1]) {
|
|
||||||
// bottom
|
|
||||||
if (distance(vec2(topLeft[0], bottomRight[1]), pixCoord) > radius) {
|
|
||||||
discard;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (pixCoord[0] > bottomRight[0]) {
|
|
||||||
// we're close right
|
|
||||||
if (pixCoord[1] < topLeft[1]) {
|
|
||||||
// top
|
|
||||||
if (distance(vec2(bottomRight[0], topLeft[1]), pixCoord) > radius) {
|
|
||||||
discard;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else if (pixCoord[1] > bottomRight[1]) {
|
|
||||||
// bottom
|
|
||||||
if (distance(bottomRight, pixCoord) > radius) {
|
|
||||||
discard;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
gl_FragColor = pixColor * alpha;
|
gl_FragColor = pixColor * alpha;
|
||||||
})#";
|
})#";
|
||||||
@@ -154,49 +240,23 @@ uniform float radius;
|
|||||||
|
|
||||||
uniform int discardOpaque;
|
uniform int discardOpaque;
|
||||||
|
|
||||||
|
uniform int primitiveMultisample;
|
||||||
|
uniform int ignoreCorners;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
|
|
||||||
if (discardOpaque == 1 && alpha == 1.0) {
|
if (discardOpaque == 1 && alpha == 1.0) {
|
||||||
discard;
|
discard;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vec4 pixColor = vec4(texture2D(tex, v_texcoord).rgb, 1.0);
|
||||||
|
|
||||||
vec2 pixCoord = fullSize * v_texcoord;
|
vec2 pixCoord = fullSize * v_texcoord;
|
||||||
|
|
||||||
if (pixCoord[0] < topLeft[0]) {
|
)#" + ROUNDED_SHADER_FUNC("pixColor") + R"#(
|
||||||
// we're close left
|
|
||||||
if (pixCoord[1] < topLeft[1]) {
|
|
||||||
// top
|
|
||||||
if (distance(topLeft, pixCoord) > radius) {
|
|
||||||
discard;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else if (pixCoord[1] > bottomRight[1]) {
|
|
||||||
// bottom
|
|
||||||
if (distance(vec2(topLeft[0], bottomRight[1]), pixCoord) > radius) {
|
|
||||||
discard;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (pixCoord[0] > bottomRight[0]) {
|
|
||||||
// we're close right
|
|
||||||
if (pixCoord[1] < topLeft[1]) {
|
|
||||||
// top
|
|
||||||
if (distance(vec2(bottomRight[0], topLeft[1]), pixCoord) > radius) {
|
|
||||||
discard;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else if (pixCoord[1] > bottomRight[1]) {
|
|
||||||
// bottom
|
|
||||||
if (distance(bottomRight, pixCoord) > radius) {
|
|
||||||
discard;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
gl_FragColor = vec4(texture2D(tex, v_texcoord).rgb, 1.0) * alpha;
|
gl_FragColor = pixColor * alpha;
|
||||||
})#";
|
})#";
|
||||||
|
|
||||||
inline const std::string FRAGBLUR1 = R"#(
|
inline const std::string FRAGBLUR1 = R"#(
|
||||||
@@ -261,6 +321,9 @@ uniform float radius;
|
|||||||
|
|
||||||
uniform int discardOpaque;
|
uniform int discardOpaque;
|
||||||
|
|
||||||
|
uniform int primitiveMultisample;
|
||||||
|
uniform int ignoreCorners;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
|
|
||||||
vec4 pixColor = texture2D(texture0, v_texcoord);
|
vec4 pixColor = texture2D(texture0, v_texcoord);
|
||||||
@@ -272,38 +335,7 @@ void main() {
|
|||||||
|
|
||||||
vec2 pixCoord = fullSize * v_texcoord;
|
vec2 pixCoord = fullSize * v_texcoord;
|
||||||
|
|
||||||
if (pixCoord[0] < topLeft[0]) {
|
)#" + ROUNDED_SHADER_FUNC("pixColor") + R"#(
|
||||||
// we're close left
|
|
||||||
if (pixCoord[1] < topLeft[1]) {
|
|
||||||
// top
|
|
||||||
if (distance(topLeft, pixCoord) > radius) {
|
|
||||||
discard;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else if (pixCoord[1] > bottomRight[1]) {
|
|
||||||
// bottom
|
|
||||||
if (distance(vec2(topLeft[0], bottomRight[1]), pixCoord) > radius) {
|
|
||||||
discard;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (pixCoord[0] > bottomRight[0]) {
|
|
||||||
// we're close right
|
|
||||||
if (pixCoord[1] < topLeft[1]) {
|
|
||||||
// top
|
|
||||||
if (distance(vec2(bottomRight[0], topLeft[1]), pixCoord) > radius) {
|
|
||||||
discard;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else if (pixCoord[1] > bottomRight[1]) {
|
|
||||||
// bottom
|
|
||||||
if (distance(bottomRight, pixCoord) > radius) {
|
|
||||||
discard;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
gl_FragColor = pixColor * alpha;
|
gl_FragColor = pixColor * alpha;
|
||||||
})#";
|
})#";
|
||||||
|
95
src/render/decorations/CHyprGroupBarDecoration.cpp
Normal file
95
src/render/decorations/CHyprGroupBarDecoration.cpp
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
#include "CHyprGroupBarDecoration.hpp"
|
||||||
|
#include "../../Compositor.hpp"
|
||||||
|
|
||||||
|
CHyprGroupBarDecoration::CHyprGroupBarDecoration(CWindow* pWindow) {
|
||||||
|
m_pWindow = pWindow;
|
||||||
|
updateWindow(pWindow);
|
||||||
|
}
|
||||||
|
|
||||||
|
CHyprGroupBarDecoration::~CHyprGroupBarDecoration() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
SWindowDecorationExtents CHyprGroupBarDecoration::getWindowDecorationExtents() {
|
||||||
|
return m_seExtents;
|
||||||
|
}
|
||||||
|
|
||||||
|
eDecorationType CHyprGroupBarDecoration::getDecorationType() {
|
||||||
|
return DECORATION_GROUPBAR;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CHyprGroupBarDecoration::updateWindow(CWindow* pWindow) {
|
||||||
|
damageEntire();
|
||||||
|
|
||||||
|
if (pWindow->m_vRealPosition.vec() != m_vLastWindowPos || pWindow->m_vRealSize.vec() != m_vLastWindowSize) {
|
||||||
|
// we draw 3px above the window's border with 3px
|
||||||
|
const auto BORDERSIZE = g_pConfigManager->getInt("general:border_size");
|
||||||
|
|
||||||
|
m_seExtents.topLeft = Vector2D(0, BORDERSIZE + 3 + 3);
|
||||||
|
m_seExtents.bottomRight = Vector2D();
|
||||||
|
|
||||||
|
m_vLastWindowPos = pWindow->m_vRealPosition.vec();
|
||||||
|
m_vLastWindowSize = pWindow->m_vRealSize.vec();
|
||||||
|
}
|
||||||
|
|
||||||
|
// let's check if the window group is different.
|
||||||
|
|
||||||
|
if (g_pLayoutManager->getCurrentLayout()->getLayoutName() != "dwindle") {
|
||||||
|
// ????
|
||||||
|
for (auto it = pWindow->m_dWindowDecorations.begin(); it != pWindow->m_dWindowDecorations.end(); it++) {
|
||||||
|
if (it->get() == this) {
|
||||||
|
pWindow->m_dWindowDecorations.erase(it);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the group info
|
||||||
|
SLayoutMessageHeader header;
|
||||||
|
header.pWindow = g_pCompositor->m_pLastWindow;
|
||||||
|
|
||||||
|
m_dwGroupMembers = std::any_cast<std::deque<CWindow*>>(g_pLayoutManager->getCurrentLayout()->layoutMessage(header, "groupinfo"));
|
||||||
|
|
||||||
|
damageEntire();
|
||||||
|
|
||||||
|
if (m_dwGroupMembers.size() == 0) {
|
||||||
|
// remove
|
||||||
|
for (auto it = pWindow->m_dWindowDecorations.begin(); it != pWindow->m_dWindowDecorations.end(); it++) {
|
||||||
|
if (it->get() == this) {
|
||||||
|
pWindow->m_dWindowDecorations.erase(it);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CHyprGroupBarDecoration::damageEntire() {
|
||||||
|
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_seExtents.topLeft.y};
|
||||||
|
g_pHyprRenderer->damageBox(&dm);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CHyprGroupBarDecoration::draw(SMonitor* pMonitor) {
|
||||||
|
// get how many bars we will draw
|
||||||
|
int barsToDraw = m_dwGroupMembers.size();
|
||||||
|
|
||||||
|
if (barsToDraw < 1 || m_pWindow->m_bHidden || !g_pCompositor->windowValidMapped(m_pWindow))
|
||||||
|
return;
|
||||||
|
|
||||||
|
const int PAD = 2; //2px
|
||||||
|
|
||||||
|
const int BARW = (m_vLastWindowSize.x - PAD * (barsToDraw - 1)) / barsToDraw;
|
||||||
|
|
||||||
|
int xoff = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < barsToDraw; ++i) {
|
||||||
|
wlr_box rect = {m_vLastWindowPos.x + xoff - pMonitor->vecPosition.x, m_vLastWindowPos.y - m_seExtents.topLeft.y - pMonitor->vecPosition.y, BARW, 3};
|
||||||
|
|
||||||
|
if (rect.width <= 0 || rect.height <= 0)
|
||||||
|
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"));
|
||||||
|
g_pHyprOpenGL->renderRect(&rect, color);
|
||||||
|
|
||||||
|
xoff += PAD + BARW;
|
||||||
|
}
|
||||||
|
}
|
30
src/render/decorations/CHyprGroupBarDecoration.hpp
Normal file
30
src/render/decorations/CHyprGroupBarDecoration.hpp
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "IHyprWindowDecoration.hpp"
|
||||||
|
#include <deque>
|
||||||
|
|
||||||
|
class CHyprGroupBarDecoration : public IHyprWindowDecoration {
|
||||||
|
public:
|
||||||
|
CHyprGroupBarDecoration(CWindow*);
|
||||||
|
virtual ~CHyprGroupBarDecoration();
|
||||||
|
|
||||||
|
virtual SWindowDecorationExtents getWindowDecorationExtents();
|
||||||
|
|
||||||
|
virtual void draw(SMonitor*);
|
||||||
|
|
||||||
|
virtual eDecorationType getDecorationType();
|
||||||
|
|
||||||
|
virtual void updateWindow(CWindow*);
|
||||||
|
|
||||||
|
virtual void damageEntire();
|
||||||
|
|
||||||
|
private:
|
||||||
|
SWindowDecorationExtents m_seExtents;
|
||||||
|
|
||||||
|
CWindow* m_pWindow = nullptr;
|
||||||
|
|
||||||
|
Vector2D m_vLastWindowPos;
|
||||||
|
Vector2D m_vLastWindowSize;
|
||||||
|
|
||||||
|
std::deque<CWindow*> m_dwGroupMembers;
|
||||||
|
};
|
7
src/render/decorations/IHyprWindowDecoration.cpp
Normal file
7
src/render/decorations/IHyprWindowDecoration.cpp
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
#include "IHyprWindowDecoration.hpp"
|
||||||
|
|
||||||
|
#include "../../Window.hpp"
|
||||||
|
|
||||||
|
IHyprWindowDecoration::~IHyprWindowDecoration() {
|
||||||
|
|
||||||
|
}
|
31
src/render/decorations/IHyprWindowDecoration.hpp
Normal file
31
src/render/decorations/IHyprWindowDecoration.hpp
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../../defines.hpp"
|
||||||
|
|
||||||
|
enum eDecorationType {
|
||||||
|
DECORATION_NONE = -1,
|
||||||
|
DECORATION_GROUPBAR
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SWindowDecorationExtents {
|
||||||
|
Vector2D topLeft;
|
||||||
|
Vector2D bottomRight;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CWindow;
|
||||||
|
struct SMonitor;
|
||||||
|
|
||||||
|
class IHyprWindowDecoration {
|
||||||
|
public:
|
||||||
|
virtual ~IHyprWindowDecoration() = 0;
|
||||||
|
|
||||||
|
virtual SWindowDecorationExtents getWindowDecorationExtents() = 0;
|
||||||
|
|
||||||
|
virtual void draw(SMonitor*) = 0;
|
||||||
|
|
||||||
|
virtual eDecorationType getDecorationType() = 0;
|
||||||
|
|
||||||
|
virtual void updateWindow(CWindow*) = 0;
|
||||||
|
|
||||||
|
virtual void damageEntire() = 0;
|
||||||
|
};
|
1
wlroots
Submodule
1
wlroots
Submodule
Submodule wlroots added at 75d31509db
Reference in New Issue
Block a user