Compare commits

...

100 Commits

Author SHA1 Message Date
vaxerski
dc5cc15474 find surfaces in reverse for focus 2022-06-10 15:18:30 +02:00
vaxerski
3a2ac11e3e added focuswindowbyclass 2022-06-10 12:06:27 +02:00
vaxerski
90a859af27 cyclenext 2022-06-10 11:41:52 +02:00
vaxerski
c6953329d5 Added circlenext 2022-06-10 11:39:06 +02:00
vaxerski
c451e13e4f Merge pull request #174 from ThatOneCalculator/main
Change features section in readme
2022-06-09 22:13:46 +02:00
vaxerski
d68e09a707 remove unfocusall 2022-06-09 22:07:33 +02:00
Kainoa Kanter
b4de91111a Update README.md 2022-06-09 12:59:30 -07:00
Kainoa Kanter
750961e9c1 Merge branch 'vaxerski:main' into main 2022-06-09 12:58:07 -07:00
vaxerski
b5a446ddfd Merge pull request #177 from vaxerski/tablets
Added Tablets support
2022-06-09 21:54:10 +02:00
vaxerski
fbc7853459 de-focusify on lost proximity 2022-06-09 21:39:03 +02:00
vaxerski
53146ccf69 oopsie 2022-06-09 21:39:03 +02:00
vaxerski
506977c13d unfocus on destroy 2022-06-09 19:40:16 +02:00
vaxerski
09b130374d unfocus tablets 2022-06-09 19:38:39 +02:00
vaxerski
b53c093b88 log tablets in hyprctl 2022-06-09 19:25:26 +02:00
vaxerski
8929172bc2 remove redundant logs 2022-06-09 19:19:42 +02:00
vaxerski
6317f64ba0 set proximity in tablets 2022-06-09 18:09:09 +02:00
vaxerski
824d8b954d logify even more 2022-06-09 17:40:05 +02:00
vaxerski
49fc1ccdb4 oops 2022-06-09 17:32:58 +02:00
vaxerski
c218ed4432 notify tablet motion 2022-06-09 17:16:01 +02:00
vaxerski
f97b90859a Add envvars to exec cfg 2022-06-09 15:03:34 +02:00
vaxerski
1841d244f0 log shit in tablets 2022-06-09 14:40:56 +02:00
vaxerski
47404534d0 added tablet v2 support (alpha alpha) 2022-06-09 12:46:55 +02:00
Kainoa Kanter
b7e21d0fa9 Update README.md 2022-06-08 14:05:06 -07:00
Kainoa Kanter
90024e534d Features 2022-06-08 14:03:54 -07:00
vaxerski
248ce66459 warn unrecognized input devices 2022-06-08 22:11:24 +02:00
vaxerski
638b44cabd Attach touch devices raw 2022-06-08 22:09:35 +02:00
vaxerski
8f0b963729 refocus after movetoworkspace 2022-06-08 15:52:38 +02:00
vaxerski
7b73570f11 fix a crash in monitorDestroy 2022-06-08 15:13:47 +02:00
vaxerski
a0f3fc794e [gha] bump flake inputs 2022-06-08 12:43:34 +00:00
vaxerski
263664c58a updated wlroots dep 2022-06-08 14:42:27 +02:00
vaxerski
da80eb8e57 Added the tablet manager and tablet v2 protocol 2022-06-08 14:29:49 +02:00
vaxerski
0b8fe2a0aa fix incorrect animationmanager behavior without anims 2022-06-07 22:27:15 +02:00
vaxerski
1642b1ff66 optimize config calls in often called areas 2022-06-07 20:41:40 +02:00
vaxerski
7b9583c1f2 Mention source in issue guidelines 2022-06-07 20:11:05 +02:00
vaxerski
cc80b68545 fixed a typo, will boost performance on opaque windows with blur 2022-06-07 20:10:14 +02:00
vaxerski
2bddfa81bc Merge pull request #169 from ThatOneCalculator/main
AUR go brrr
2022-06-07 00:12:30 +02:00
Kainoa Kanter
85d91c3d3c Update PKGBUILD-git 2022-06-06 15:07:48 -07:00
Kainoa Kanter
d80c90233b Update PKGBUILD-bin 2022-06-06 15:07:35 -07:00
Kainoa Kanter
d0ca043122 Update PKGBUILD-git 2022-06-06 15:05:29 -07:00
Kainoa Kanter
92da453d4d Update PKGBUILD-git 2022-06-06 15:05:16 -07:00
Kainoa Kanter
433e4a0eef Update PKGBUILD 2022-06-06 15:05:00 -07:00
vaxerski
b62e530fdb Force window style tiled on all xdg windows 2022-06-06 19:43:44 +02:00
vaxerski
663fba76ae Added resizeactive 2022-06-06 19:32:14 +02:00
vaxerski
d73e05cc68 fix XDELTA and YDELTA with empty geometry 2022-06-06 18:56:16 +02:00
vaxerski
066ea296ff dont report unmanaged x11 windows in hyprctl clients 2022-06-06 15:22:25 +02:00
vaxerski
72c967aa89 fix class crash with unmanaged x11 2022-06-06 15:03:06 +02:00
vaxerski
c474e8253a Update issue templates 2022-06-06 15:00:24 +02:00
vaxerski
20936ad2a4 added issue guidelines 2022-06-06 14:58:50 +02:00
vaxerski
d743ac7bb1 added forcerendererreload and some more vt changes 2022-06-06 13:48:17 +02:00
vaxerski
322a495412 Merge pull request #167 from JamesReynolds/main
Fix error: attribute 'lastModifiedDate' missing
2022-06-06 13:06:40 +02:00
vaxerski
63d6c594b9 fix possible crash in hyprctl clients 2022-06-06 12:58:39 +02:00
vaxerski
09e77bf844 added force_no_accel 2022-06-06 12:08:33 +02:00
James Reynolds
3d4832990c Fix error: attribute 'lastModifiedDate' missing
Only applies to some versions of flakes, tested on nix 2.8.1.
2022-06-06 10:20:56 +01:00
vaxerski
84a0fa0f34 fix subsurfaces not damaging on unmap 2022-06-05 23:23:16 +02:00
vaxerski
2cd2f8b5b5 add class to window hyprctl requests 2022-06-04 20:32:27 +02:00
vaxerski
172d6cd498 Merge pull request #160 from ThatOneCalculator/main
Hooray, more AUR stuff!
2022-06-03 20:41:10 +02:00
Kainoa Kanter
02269af777 Update PKGBUILD-git 2022-06-03 11:33:32 -07:00
Kainoa Kanter
e2592522d3 Update PKGBUILD 2022-06-03 11:33:14 -07:00
Kainoa Kanter
d76c982d2e Update PKGBUILD-bin 2022-06-03 11:32:48 -07:00
vaxerski
ef855440c6 keyboard code further cleanup 2022-06-03 19:15:39 +02:00
vaxerski
246aa000f5 Added dwindle:special_scale_factor 2022-06-03 19:03:33 +02:00
vaxerski
1a93b2a756 Handle keyboards better
Also fixes some crashes of apps on reload
2022-06-03 18:59:39 +02:00
vaxerski
10c2bd0686 make shaders cleaner 2022-06-03 18:45:18 +02:00
vaxerski
f99ad521a4 Updated issue templates 2022-06-03 17:52:22 +02:00
vaxerski
9486a230c7 Log to the instance folder 2022-06-03 17:48:07 +02:00
vaxerski
6f3b004199 IPC and log changes, introduce signature 2022-06-03 17:41:57 +02:00
vaxerski
19b17b590c fix moveactivetoworkspace with same workspace 2022-06-03 11:19:17 +02:00
vaxerski
f9c8a72e46 dont enable AA by default 2022-06-02 23:03:13 +02:00
vaxerski
e11cb8b328 Added antialiasing to outer edges
simplified, stupidly fast MSAA for rounded edges
2022-06-02 22:58:54 +02:00
vaxerski
7b568d7ad8 configure keyboards one by one 2022-06-02 20:31:47 +02:00
vaxerski
a2f718059b fucking typo 2022-06-02 19:50:46 +02:00
vaxerski
feb0499597 Merge pull request #144 from fufexan/main
Fix Nix build and add updater
2022-06-02 19:47:54 +02:00
vaxerski
601abc7e92 Added locking numlock 2022-06-02 19:47:11 +02:00
Mihai Fufezan
7451890fd7 nix: replace paths dynamically 2022-06-02 19:10:56 +03:00
vaxerski
f5cdb5b95e Fix special in m+1 m-1 2022-06-02 16:54:19 +02:00
vaxerski
7afcf656bd Added hyprctl devices 2022-06-02 13:59:33 +02:00
Mihai Fufezan
6daa866beb nix/updater: only update wlroots on rev change 2022-06-02 00:09:28 +03:00
Mihai Fufezan
9447fcd603 fix Nix build and add updater
- move unnecessary toplevel files to nix/
- added patch that ignores the submodule (revert)
- add update script run by a workflow
2022-06-01 23:52:08 +03:00
vaxerski
9acf15efd7 README changes 2022-06-01 22:00:46 +02:00
vaxerski
b5a100379e reject drag on fullscreen workspace 2022-06-01 21:13:10 +02:00
vaxerski
4f76d5d8d7 destroy monitor on disabled 2022-06-01 21:10:12 +02:00
vaxerski
8d850b0ce1 Added workspace/monitor unset and workspace silent rules 2022-06-01 21:04:06 +02:00
vaxerski
0f28d2ae55 fix stupid error in anim styles 2022-06-01 20:51:21 +02:00
vaxerski
d2451aea4b use overflowing coords when surface unmaps 2022-06-01 13:38:33 +02:00
vaxerski
680705ff91 [gha] bump flake inputs 2022-06-01 00:50:00 +00:00
vaxerski
300fc2ab0f Merge pull request #140 from ThatOneCalculator/main
More AUR stuff
2022-05-31 22:49:15 +02:00
Kainoa Kanter
02210d3d96 Update PKGBUILD-bin 2022-05-31 13:46:09 -07:00
Kainoa Kanter
879345c1e9 Update PKGBUILD-git 2022-05-31 13:46:00 -07:00
Kainoa Kanter
1e3bea5e70 Update PKGBUILD 2022-05-31 13:45:51 -07:00
Kainoa Kanter
f64cae2b7f Update PKGBUILD-bin 2022-05-31 13:32:59 -07:00
Kainoa Kanter
c433b14e3d Update PKGBUILD 2022-05-31 13:32:38 -07:00
Kainoa Kanter
8d1c495878 Update PKGBUILD-git 2022-05-31 13:32:26 -07:00
Kainoa Kanter
4264a0b08d Update PKGBUILD 2022-05-31 13:26:03 -07:00
Kainoa Kanter
40ab062a3c Update PKGBUILD-bin 2022-05-31 13:25:49 -07:00
Kainoa Kanter
35bcea38e3 0.2.1beta 2022-05-31 13:19:26 -07:00
Kainoa Kanter
1ccb944509 0.2.1beta 2022-05-31 13:19:15 -07:00
Kainoa Kanter
c600249aee Merge branch 'vaxerski:main' into main 2022-05-31 13:18:36 -07:00
Kainoa Kanter
6d6e967a8d Update PKGBUILD-git 2022-05-31 13:17:02 -07:00
Kainoa Kanter
f6b8a96621 Update PKGBUILD 2022-05-31 13:15:57 -07:00
Kainoa Kanter
8e8d5a99c2 Add bin 2022-05-31 13:15:41 -07:00
54 changed files with 2558 additions and 480 deletions

View File

@@ -7,12 +7,6 @@ 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>)
*Please do NOT attach coredumps from any packaged version of Hyprland (AUR, etc.). Compile manually, and THEN attach a coredump of that.*

View File

@@ -7,4 +7,6 @@ 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.

View File

@@ -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"

View File

@@ -59,6 +59,16 @@ pointer-constraints-unstable-v1-protocol.c:
pointer-constraints-unstable-v1-protocol.o: pointer-constraints-unstable-v1-protocol.h pointer-constraints-unstable-v1-protocol.o: pointer-constraints-unstable-v1-protocol.h
tablet-unstable-v2-protocol.h:
$(WAYLAND_SCANNER) server-header \
protocols/tablet-unstable-v2.xml $@
tablet-unstable-v2-protocol.c:
$(WAYLAND_SCANNER) private-code \
protocols/tablet-unstable-v2.xml $@
tablet-unstable-v2-protocol.o: tablet-unstable-v2-protocol.h
idle-protocol.h: idle-protocol.h:
$(WAYLAND_SCANNER) server-header \ $(WAYLAND_SCANNER) server-header \
protocols/idle.xml $@ protocols/idle.xml $@
@@ -114,7 +124,7 @@ uninstall:
rm -f ${PREFIX}/bin/hyprctl rm -f ${PREFIX}/bin/hyprctl
rm -rf ${PREFIX}/share/hyprland rm -rf ${PREFIX}/share/hyprland
protocols: xdg-shell-protocol.o wlr-layer-shell-unstable-v1-protocol.o wlr-screencopy-unstable-v1-protocol.o idle-protocol.o ext-workspace-unstable-v1-protocol.o pointer-constraints-unstable-v1-protocol.o protocols: xdg-shell-protocol.o wlr-layer-shell-unstable-v1-protocol.o wlr-screencopy-unstable-v1-protocol.o idle-protocol.o ext-workspace-unstable-v1-protocol.o pointer-constraints-unstable-v1-protocol.o tablet-unstable-v2-protocol.o
config: config:
make protocols make protocols

View File

@@ -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
@@ -52,18 +51,22 @@ Try it out and report bugs / suggestions!
- Easily expandable and readable codebase - Easily expandable and readable codebase
- Config reloaded instantly upon saving - Config reloaded instantly upon saving
- Custom bezier curve based animations - Custom bezier curve based animations
- wlr_ext workspaces protocol support - `wlr_ext` workspaces protocol support
- Dual Kawase blur - Dual Kawase blur
- Fully dynamic workspaces - Fully dynamic workspaces
- Window / layer fade in / out - Closely follows `wlroots-git`
- Tiling/floating/fullscreen windows - Bundled wlroots
- Special Workspace (Scratchpad) - Window/layer fade in/out
- Window/monitor rules - Tiling/pseudotiling/floating/fullscreen windows
- Switching workspaces between window modes on the fly
- Special workspace (scratchpad)
- Window/monitor rules
- Socket-based IPC - Socket-based IPC
- Event System for bash scripts - Event system for bash scripts
- Rounded corners - Rounded corners
- Full Damage tracking - Full damage tracking
- Docks support - Docks support
- Drawing tablet support
<br> <br>
<br> <br>

View File

@@ -2,20 +2,60 @@
_pkgname="hyprland" _pkgname="hyprland"
pkgname="${_pkgname}" pkgname="${_pkgname}"
pkgver="0.1.1beta" pkgver="0.4.0beta"
pkgrel=2 pkgrel=2
pkgdesc="Hyprland is a dynamic tiling Wayland compositor based on wlroots that doesn't sacrifice on its looks." pkgdesc="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}-${pkgver}.tar.gz::https://github.com/vaxerski/hyprland/archive/v${pkgver}.tar.gz") source=("${pkgname}-${pkgver}.tar.gz::https://github.com/vaxerski/hyprland/archive/v${pkgver}.tar.gz")
sha256sums=('SKIP') sha256sums=('5969e5f88426f90acdfb5958644733d8a9409389c2d345514c58a66cf74d2f91')
conflicts=("${_pkgname}")
provides=(hyprland)
options=(!makeflags !buildflags) options=(!makeflags !buildflags)
build() { build() {
cd "$srcdir/Hyprland-$pkgver" cd "$srcdir/Hyprland-$pkgver"
git submodule update --init
make all make all
} }

56
aur/PKGBUILD-bin Normal file
View File

@@ -0,0 +1,56 @@
# Maintainer: ThatOneCalculator <kainoa@t1c.dev>
_pkgname="hyprland"
pkgname="${_pkgname}-bin"
pkgver="0.4.0beta"
pkgrel=2
pkgdesc="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=('5969e5f88426f90acdfb5958644733d8a9409389c2d345514c58a66cf74d2f91')
conflicts=("${_pkgname}")
provides=(hyprland)
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}"
}

View File

@@ -2,15 +2,54 @@
_pkgname="hyprland" _pkgname="hyprland"
pkgname="${_pkgname}-git" pkgname="${_pkgname}-git"
pkgver=r568.g632d00c pkgver=r673.gb62e530
pkgrel=1 pkgrel=2
pkgdesc="Hyprland is a dynamic tiling Wayland compositor based on wlroots that doesn't sacrifice on its looks." pkgdesc="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}")
provides=(hyprland)
sha256sums=('SKIP') sha256sums=('SKIP')
options=(!makeflags !buildflags) options=(!makeflags !buildflags)
@@ -24,6 +63,7 @@ pkgver() {
build() { build() {
cd "${srcdir}/${_pkgname}" cd "${srcdir}/${_pkgname}"
git submodule update --init
make all make all
} }

View File

@@ -1,32 +0,0 @@
# Contributing
*Thank you for considering contributing to Hyprland.*
## Development
Check the[Wiki]for debugging instructions.
Afterwards, pick yourself an[Issue] orimplement your own suggestion.
An good place to search for things to contribute is the [Projects Page]
*As Hyprlandis 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

58
docs/ISSUE_GUIDELINES.md Normal file
View File

@@ -0,0 +1,58 @@
# 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)
**Important**: Please do NOT use any package for reporting bugs! Clone and compile from source.
## 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.

View File

@@ -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

12
flake.lock generated
View File

@@ -2,11 +2,11 @@
"nodes": { "nodes": {
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1653581809, "lastModified": 1654593855,
"narHash": "sha256-Uvka0V5MTGbeOfWte25+tfRL3moECDh1VwokWSZUdoY=", "narHash": "sha256-c+SyXvj7THre87OyIdZfRVR+HhI/g1ZDrQ3VUtTuHkU=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "83658b28fe638a170a19b8933aa008b30640fbd1", "rev": "033bd4fa9a8fbe0c68a88e925d9a884161044b25",
"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": 1653733431, "lastModified": 1654618691,
"narHash": "sha256-0JwNH2E9XlMVa7ZCsqxazpKwpZ2rW5QQjbk0DdZxa48=", "narHash": "sha256-8y3u8CoigjoZOVbA2wCWBHlDNEakv0AVxU46/cOC00s=",
"owner": "wlroots", "owner": "wlroots",
"repo": "wlroots", "repo": "wlroots",
"rev": "93ee4c7684050807e959bb3b6d57826a72fba8c2", "rev": "b89ed9015c3fbe8d339e9d65cf70fdca6e5645bc",
"type": "gitlab" "type": "gitlab"
}, },
"original": { "original": {

View File

@@ -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: {

View File

@@ -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);

View File

@@ -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
View 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

File diff suppressed because it is too large Load Diff

View File

@@ -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();
@@ -104,6 +109,8 @@ CCompositor::CCompositor() {
m_sWLRVirtPtrMgr = wlr_virtual_pointer_manager_v1_create(m_sWLDisplay); m_sWLRVirtPtrMgr = wlr_virtual_pointer_manager_v1_create(m_sWLDisplay);
m_sWLRToplevelMgr = wlr_foreign_toplevel_manager_v1_create(m_sWLDisplay); m_sWLRToplevelMgr = wlr_foreign_toplevel_manager_v1_create(m_sWLDisplay);
m_sWLRTabletManager = wlr_tablet_v2_create(m_sWLDisplay);
} }
CCompositor::~CCompositor() { CCompositor::~CCompositor() {
@@ -137,6 +144,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);
@@ -577,11 +585,11 @@ CWindow* CCompositor::getWindowForPopup(wlr_xdg_popup* popup) {
} }
wlr_surface* CCompositor::vectorToLayerSurface(const Vector2D& pos, std::list<SLayerSurface*>* layerSurfaces, Vector2D* sCoords) { wlr_surface* CCompositor::vectorToLayerSurface(const Vector2D& pos, std::list<SLayerSurface*>* layerSurfaces, Vector2D* sCoords) {
for (auto& l : *layerSurfaces) { for (auto it = layerSurfaces->rbegin(); it != layerSurfaces->rend(); it++) {
if (l->fadingOut || (l->layerSurface && !l->layerSurface->mapped)) if ((*it)->fadingOut || !(*it)->layerSurface || ((*it)->layerSurface && !(*it)->layerSurface->mapped))
continue; continue;
const auto SURFACEAT = wlr_layer_surface_v1_surface_at(l->layerSurface, pos.x - l->geometry.x, pos.y - l->geometry.y, &sCoords->x, &sCoords->y); const auto SURFACEAT = wlr_layer_surface_v1_surface_at((*it)->layerSurface, pos.x - (*it)->geometry.x, pos.y - (*it)->geometry.y, &sCoords->x, &sCoords->y);
if (SURFACEAT) if (SURFACEAT)
return SURFACEAT; return SURFACEAT;

View File

@@ -10,7 +10,7 @@
#include "config/ConfigManager.hpp" #include "config/ConfigManager.hpp"
#include "managers/ThreadManager.hpp" #include "managers/ThreadManager.hpp"
#include "managers/XWaylandManager.hpp" #include "managers/XWaylandManager.hpp"
#include "managers/InputManager.hpp" #include "managers/input/InputManager.hpp"
#include "managers/LayoutManager.hpp" #include "managers/LayoutManager.hpp"
#include "managers/KeybindManager.hpp" #include "managers/KeybindManager.hpp"
#include "managers/AnimationManager.hpp" #include "managers/AnimationManager.hpp"
@@ -59,10 +59,12 @@ public:
wlr_xdg_decoration_manager_v1* m_sWLRXDGDecoMgr; wlr_xdg_decoration_manager_v1* m_sWLRXDGDecoMgr;
wlr_virtual_pointer_manager_v1* m_sWLRVirtPtrMgr; wlr_virtual_pointer_manager_v1* m_sWLRVirtPtrMgr;
wlr_foreign_toplevel_manager_v1* m_sWLRToplevelMgr; wlr_foreign_toplevel_manager_v1* m_sWLRToplevelMgr;
wlr_tablet_manager_v2* m_sWLRTabletManager;
// ------------------------------------------------- // // ------------------------------------------------- //
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;

View File

@@ -45,12 +45,14 @@ void CConfigManager::setDefaultVars() {
configValues["decoration:active_opacity"].floatValue = 1; configValues["decoration:active_opacity"].floatValue = 1;
configValues["decoration:inactive_opacity"].floatValue = 1; configValues["decoration:inactive_opacity"].floatValue = 1;
configValues["decoration:fullscreen_opacity"].floatValue = 1; configValues["decoration:fullscreen_opacity"].floatValue = 1;
configValues["decoration:multisample_edges"].intValue = 0;
configValues["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;
@@ -80,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;
@@ -152,8 +156,18 @@ void CConfigManager::configSetValueSafe(const std::string& COMMAND, const std::s
void CConfigManager::handleRawExec(const std::string& command, const std::string& args) { void CConfigManager::handleRawExec(const std::string& command, const std::string& args) {
// Exec in the background dont wait for it. // Exec in the background dont wait for it.
std::string toExec = args;
if (g_pXWaylandManager->m_sWLRXWayland)
toExec = std::string("WAYLAND_DISPLAY=") + std::string(g_pCompositor->m_szWLDisplaySocket) + " DISPLAY=" + std::string(g_pXWaylandManager->m_sWLRXWayland->display_name) + " " + toExec;
else
toExec = std::string("WAYLAND_DISPLAY=") + std::string(g_pCompositor->m_szWLDisplaySocket) + " " + toExec;
Debug::log(LOG, "Config executing %s", toExec.c_str());
if (fork() == 0) { if (fork() == 0) {
execl("/bin/sh", "/bin/sh", "-c", args.c_str(), nullptr); execl("/bin/sh", "/bin/sh", "-c", toExec.c_str(), nullptr);
_exit(0); _exit(0);
} }

View File

@@ -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\tmonitor: %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, w.m_iMonitorID); 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\tmonitor: %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, (int)PWINDOW->m_iMonitorID); 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,38 @@ 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);
}
result += "\n\nTablets:\n";
for (auto& d : g_pInputManager->m_lTabletPads) {
result += getFormat("\tTablet Pad at %x (belongs to %x -> %s)\n", &d, d.pTabletParent, d.pTabletParent ? d.pTabletParent->wlrDevice ? d.pTabletParent->wlrDevice->name : "" : "");
}
for (auto& d : g_pInputManager->m_lTablets) {
result += getFormat("\tTablet at %x:\n\t\t%s\n", &d, d.wlrDevice ? d.wlrDevice->name : "");
}
for (auto& d : g_pInputManager->m_lTabletTools) {
result += getFormat("\tTablet Tool at %x (belongs to %x)\n", &d, d.wlrTabletTool ? d.wlrTabletTool->data : 0);
}
return result;
}
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 +219,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 +281,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 +297,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);

View File

@@ -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:

View File

@@ -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;
}; };

View File

@@ -2,7 +2,7 @@
#include "../Compositor.hpp" #include "../Compositor.hpp"
#include "../helpers/WLClasses.hpp" #include "../helpers/WLClasses.hpp"
#include "../managers/InputManager.hpp" #include "../managers/input/InputManager.hpp"
#include "../render/Renderer.hpp" #include "../render/Renderer.hpp"
// ---------------------------------------------------- // // ---------------------------------------------------- //
@@ -73,13 +73,25 @@ void Events::listener_newInput(wl_listener* listener, void* data) {
Debug::log(LOG, "Attached a mouse with name %s", DEVICE->name); Debug::log(LOG, "Attached a mouse with name %s", DEVICE->name);
g_pInputManager->newMouse(DEVICE); g_pInputManager->newMouse(DEVICE);
break; break;
case WLR_INPUT_DEVICE_TOUCH:
Debug::log(LOG, "Attached a touch device with name %s", DEVICE->name);
Debug::log(WARN, "!!!! Hyprland does not directly support touchscreens, bugs may occur !!!!");
wlr_cursor_attach_input_device(g_pCompositor->m_sWLRCursor, DEVICE);
break;
case WLR_INPUT_DEVICE_TABLET_TOOL:
Debug::log(LOG, "Attached a tablet tool with name %s", DEVICE->name);
g_pInputManager->newTabletTool(DEVICE);
break;
case WLR_INPUT_DEVICE_TABLET_PAD:
Debug::log(LOG, "Attached a tablet pad with name %s", DEVICE->name);
g_pInputManager->newTabletPad(DEVICE);
break;
default: default:
Debug::log(WARN, "Unrecognized input device plugged in: %s", DEVICE->name);
break; break;
} }
uint32_t capabilities = WL_SEAT_CAPABILITY_POINTER | WL_SEAT_CAPABILITY_KEYBOARD; g_pInputManager->updateCapabilities(DEVICE);
wlr_seat_set_capabilities(g_pCompositor->m_sSeat.seat, capabilities);
} }
void Events::listener_newConstraint(wl_listener* listener, void* data) { void Events::listener_newConstraint(wl_listener* listener, void* data) {

View File

@@ -109,4 +109,7 @@ namespace Events {
// Deco XDG // Deco XDG
LISTENER(NewXDGDeco); LISTENER(NewXDGDeco);
// Renderer destroy
LISTENER(RendererDestroy);
}; };

View File

@@ -1,6 +1,6 @@
#include "../Compositor.hpp" #include "../Compositor.hpp"
#include "../helpers/WLClasses.hpp" #include "../helpers/WLClasses.hpp"
#include "../managers/InputManager.hpp" #include "../managers/input/InputManager.hpp"
#include "../render/Renderer.hpp" #include "../render/Renderer.hpp"
#include "Events.hpp" #include "Events.hpp"
@@ -26,7 +26,7 @@ void Events::listener_newLayerSurface(wl_listener* listener, void* data) {
return; return;
} }
Debug::log(LOG, "New LayerSurface has no preferred monitor. Assigning Monitor %s", PMONITOR->szName); Debug::log(LOG, "New LayerSurface has no preferred monitor. Assigning Monitor %s", PMONITOR->szName.c_str());
WLRLAYERSURFACE->output = PMONITOR->output; WLRLAYERSURFACE->output = PMONITOR->output;
} }
@@ -160,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) {

View File

@@ -2,7 +2,7 @@
#include "../Compositor.hpp" #include "../Compositor.hpp"
#include "../helpers/WLClasses.hpp" #include "../helpers/WLClasses.hpp"
#include "../managers/InputManager.hpp" #include "../managers/input/InputManager.hpp"
#include "../render/Renderer.hpp" #include "../render/Renderer.hpp"
// ------------------------------ // // ------------------------------ //
@@ -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!!");
} }

View File

@@ -1,6 +1,6 @@
#include "../Compositor.hpp" #include "../Compositor.hpp"
#include "../helpers/WLClasses.hpp" #include "../helpers/WLClasses.hpp"
#include "../managers/InputManager.hpp" #include "../managers/input/InputManager.hpp"
#include "../render/Renderer.hpp" #include "../render/Renderer.hpp"
#include "Events.hpp" #include "Events.hpp"
#include "../debug/HyprCtl.hpp" #include "../debug/HyprCtl.hpp"
@@ -65,6 +65,10 @@ 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;
} }
@@ -156,7 +160,10 @@ void Events::listener_monitorFrame(void* owner, void* data) {
static std::chrono::high_resolution_clock::time_point startRenderOverlay = std::chrono::high_resolution_clock::now(); static std::chrono::high_resolution_clock::time_point startRenderOverlay = std::chrono::high_resolution_clock::now();
static std::chrono::high_resolution_clock::time_point endRenderOverlay = std::chrono::high_resolution_clock::now(); static std::chrono::high_resolution_clock::time_point endRenderOverlay = std::chrono::high_resolution_clock::now();
if (g_pConfigManager->getInt("debug:overlay") == 1) { static auto *const PDEBUGOVERLAY = &g_pConfigManager->getConfigValuePtr("debug:overlay")->intValue;
static auto *const PDAMAGETRACKINGMODE = &g_pConfigManager->getConfigValuePtr("general:damage_tracking_internal")->intValue;
if (*PDEBUGOVERLAY == 1) {
startRender = std::chrono::high_resolution_clock::now(); startRender = std::chrono::high_resolution_clock::now();
g_pDebugOverlay->frameData(PMONITOR); g_pDebugOverlay->frameData(PMONITOR);
} }
@@ -176,9 +183,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;
} }
@@ -191,9 +203,7 @@ void Events::listener_monitorFrame(void* owner, void* data) {
bool hasChanged; bool hasChanged;
pixman_region32_init(&damage); pixman_region32_init(&damage);
const auto DTMODE = g_pConfigManager->getInt("general:damage_tracking_internal"); if (*PDAMAGETRACKINGMODE == -1) {
if (DTMODE == -1) {
Debug::log(CRIT, "Damage tracking mode -1 ????"); Debug::log(CRIT, "Damage tracking mode -1 ????");
return; return;
} }
@@ -203,7 +213,7 @@ void Events::listener_monitorFrame(void* owner, void* data) {
return; return;
} }
if (!hasChanged && DTMODE != DAMAGE_TRACKING_NONE) { if (!hasChanged && *PDAMAGETRACKINGMODE != DAMAGE_TRACKING_NONE) {
pixman_region32_fini(&damage); pixman_region32_fini(&damage);
wlr_output_rollback(PMONITOR->output); wlr_output_rollback(PMONITOR->output);
wlr_output_schedule_frame(PMONITOR->output); // we update shit at the monitor's Hz so we need to schedule frames because rollback wont wlr_output_schedule_frame(PMONITOR->output); // we update shit at the monitor's Hz so we need to schedule frames because rollback wont
@@ -211,19 +221,19 @@ void Events::listener_monitorFrame(void* owner, void* data) {
} }
// if we have no tracking or full tracking, invalidate the entire monitor // if we have no tracking or full tracking, invalidate the entire monitor
if (DTMODE == DAMAGE_TRACKING_NONE || DTMODE == DAMAGE_TRACKING_MONITOR) { if (*PDAMAGETRACKINGMODE == DAMAGE_TRACKING_NONE || *PDAMAGETRACKINGMODE == DAMAGE_TRACKING_MONITOR) {
pixman_region32_union_rect(&damage, &damage, 0, 0, (int)PMONITOR->vecTransformedSize.x, (int)PMONITOR->vecTransformedSize.y); pixman_region32_union_rect(&damage, &damage, 0, 0, (int)PMONITOR->vecTransformedSize.x, (int)PMONITOR->vecTransformedSize.y);
pixman_region32_copy(&g_pHyprOpenGL->m_rOriginalDamageRegion, &damage); pixman_region32_copy(&g_pHyprOpenGL->m_rOriginalDamageRegion, &damage);
} else { } else {
static auto* const PBLURENABLED = &g_pConfigManager->getConfigValuePtr("decoration:blur")->intValue;
// if we use blur we need to expand the damage for proper blurring // if we use blur we need to expand the damage for proper blurring
if (g_pConfigManager->getInt("decoration:blur") == 1) { if (*PBLURENABLED == 1) {
// TODO: can this be optimized? // TODO: can this be optimized?
const auto BLURSIZE = g_pConfigManager->getInt("decoration:blur_size"); static auto* const PBLURSIZE = &g_pConfigManager->getConfigValuePtr("decoration:blur_size")->intValue;
const auto BLURPASSES = g_pConfigManager->getInt("decoration:blur_passes"); static auto* const PBLURPASSES = &g_pConfigManager->getConfigValuePtr("decoration:blur_passes")->intValue;
const auto BLURRADIUS = *PBLURSIZE * pow(2, *PBLURPASSES); // is this 2^pass? I don't know but it works... I think.
const auto BLURRADIUS = BLURSIZE * pow(2, BLURPASSES); // is this 2^pass? I don't know but it works... I think.
pixman_region32_copy(&g_pHyprOpenGL->m_rOriginalDamageRegion, &damage); pixman_region32_copy(&g_pHyprOpenGL->m_rOriginalDamageRegion, &damage);
@@ -248,7 +258,7 @@ void Events::listener_monitorFrame(void* owner, void* data) {
g_pHyprError->draw(); g_pHyprError->draw();
// for drawing the debug overlay // for drawing the debug overlay
if (PMONITOR->ID == 0 && g_pConfigManager->getInt("debug:overlay") == 1) { if (PMONITOR->ID == 0 && *PDEBUGOVERLAY == 1) {
startRenderOverlay = std::chrono::high_resolution_clock::now(); startRenderOverlay = std::chrono::high_resolution_clock::now();
g_pDebugOverlay->draw(); g_pDebugOverlay->draw();
endRenderOverlay = std::chrono::high_resolution_clock::now(); endRenderOverlay = std::chrono::high_resolution_clock::now();
@@ -269,7 +279,7 @@ void Events::listener_monitorFrame(void* owner, void* data) {
const auto TRANSFORM = wlr_output_transform_invert(PMONITOR->output->transform); const auto TRANSFORM = wlr_output_transform_invert(PMONITOR->output->transform);
wlr_region_transform(&frameDamage, &PMONITOR->damage->current, TRANSFORM, (int)PMONITOR->vecTransformedSize.x, (int)PMONITOR->vecTransformedSize.y); wlr_region_transform(&frameDamage, &PMONITOR->damage->current, TRANSFORM, (int)PMONITOR->vecTransformedSize.x, (int)PMONITOR->vecTransformedSize.y);
if (DTMODE == DAMAGE_TRACKING_NONE || DTMODE == DAMAGE_TRACKING_MONITOR) if (*PDAMAGETRACKINGMODE == DAMAGE_TRACKING_NONE || *PDAMAGETRACKINGMODE == DAMAGE_TRACKING_MONITOR)
pixman_region32_union_rect(&frameDamage, &frameDamage, 0, 0, (int)PMONITOR->vecTransformedSize.x, (int)PMONITOR->vecTransformedSize.y); pixman_region32_union_rect(&frameDamage, &frameDamage, 0, 0, (int)PMONITOR->vecTransformedSize.x, (int)PMONITOR->vecTransformedSize.y);
wlr_output_set_damage(PMONITOR->output, &frameDamage); wlr_output_set_damage(PMONITOR->output, &frameDamage);
@@ -280,7 +290,7 @@ void Events::listener_monitorFrame(void* owner, void* data) {
wlr_output_schedule_frame(PMONITOR->output); wlr_output_schedule_frame(PMONITOR->output);
if (g_pConfigManager->getInt("debug:overlay") == 1) { if (*PDEBUGOVERLAY == 1) {
const float µs = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now() - startRender).count() / 1000.f; const float µs = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now() - startRender).count() / 1000.f;
g_pDebugOverlay->renderData(PMONITOR, µs); g_pDebugOverlay->renderData(PMONITOR, µs);
if (PMONITOR->ID == 0) { if (PMONITOR->ID == 0) {
@@ -309,14 +319,16 @@ void Events::listener_monitorDestroy(void* owner, void* data) {
// Cleanup everything. Move windows back, snap cursor, shit. // Cleanup everything. Move windows back, snap cursor, shit.
const auto BACKUPMON = &g_pCompositor->m_lMonitors.front(); const auto BACKUPMON = &g_pCompositor->m_lMonitors.front();
const auto BACKUPWORKSPACE = BACKUPMON->activeWorkspace > 0 ? std::to_string(BACKUPMON->activeWorkspace) : "name:" + g_pCompositor->getWorkspaceByID(BACKUPMON->activeWorkspace)->m_szName;
if (!BACKUPMON) { if (!BACKUPMON) {
Debug::log(CRIT, "No monitors! Unplugged last! Exiting."); Debug::log(CRIT, "No monitors! Unplugged last! Exiting.");
g_pCompositor->cleanupExit(); g_pCompositor->cleanupExit();
exit(1);
return; return;
} }
const auto BACKUPWORKSPACE = BACKUPMON->activeWorkspace > 0 ? std::to_string(BACKUPMON->activeWorkspace) : "name:" + g_pCompositor->getWorkspaceByID(BACKUPMON->activeWorkspace)->m_szName;
// snap cursor // snap cursor
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sSeat.mouse->mouse, BACKUPMON->vecPosition.x + BACKUPMON->vecTransformedSize.x / 2.f, BACKUPMON->vecPosition.y + BACKUPMON->vecTransformedSize.y / 2.f); wlr_cursor_warp(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sSeat.mouse->mouse, BACKUPMON->vecPosition.x + BACKUPMON->vecTransformedSize.x / 2.f, BACKUPMON->vecPosition.y + BACKUPMON->vecTransformedSize.y / 2.f);

View File

@@ -2,7 +2,7 @@
#include "../Compositor.hpp" #include "../Compositor.hpp"
#include "../helpers/WLClasses.hpp" #include "../helpers/WLClasses.hpp"
#include "../managers/InputManager.hpp" #include "../managers/input/InputManager.hpp"
#include "../render/Renderer.hpp" #include "../render/Renderer.hpp"
// --------------------------------------------- // // --------------------------------------------- //

View File

@@ -2,7 +2,7 @@
#include "../Compositor.hpp" #include "../Compositor.hpp"
#include "../helpers/WLClasses.hpp" #include "../helpers/WLClasses.hpp"
#include "../managers/InputManager.hpp" #include "../managers/input/InputManager.hpp"
#include "../render/Renderer.hpp" #include "../render/Renderer.hpp"
// ------------------------------------------------------------ // // ------------------------------------------------------------ //
@@ -35,6 +35,9 @@ void Events::listener_mapWindow(void* owner, void* data) {
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 // Foreign Toplevel
PWINDOW->m_phForeignToplevel = wlr_foreign_toplevel_handle_v1_create(g_pCompositor->m_sWLRToplevelMgr); PWINDOW->m_phForeignToplevel = wlr_foreign_toplevel_handle_v1_create(g_pCompositor->m_sWLRToplevelMgr);
// TODO: handle foreign events (requests) // TODO: handle foreign events (requests)
@@ -73,16 +76,23 @@ void Events::listener_mapWindow(void* owner, void* data) {
// window rules // window rules
const auto WINDOWRULES = g_pConfigManager->getMatchingRules(PWINDOW); const auto WINDOWRULES = g_pConfigManager->getMatchingRules(PWINDOW);
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;
@@ -91,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) {
@@ -132,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;
@@ -205,6 +237,15 @@ void Events::listener_mapWindow(void* owner, void* data) {
// do the animation thing // do the animation thing
g_pAnimationManager->onWindowPostCreateClose(PWINDOW, false); 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);
} }

View File

@@ -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) {
@@ -172,7 +191,7 @@ int getWorkspaceIDFromString(const std::string& in, std::string& outName) {
searchID = lowestID; searchID = lowestID;
} }
if (const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(searchID); PWORKSPACE) { if (const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(searchID); PWORKSPACE && PWORKSPACE->m_iID != SPECIAL_WORKSPACE_ID) {
if (PWORKSPACE->m_iMonitorID == g_pCompositor->m_pLastMonitor->ID) { if (PWORKSPACE->m_iMonitorID == g_pCompositor->m_pLastMonitor->ID) {
currentID = PWORKSPACE->m_iID; currentID = PWORKSPACE->m_iID;

View File

@@ -27,7 +27,8 @@ 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; wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL;
// for the special workspace // for the special workspace

View File

@@ -89,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");
@@ -162,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;
} }

View File

@@ -69,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;
@@ -151,4 +153,56 @@ struct SDrag {
DYNLISTENER(mapIcon); DYNLISTENER(mapIcon);
DYNLISTENER(unmapIcon); DYNLISTENER(unmapIcon);
DYNLISTENER(commitIcon); DYNLISTENER(commitIcon);
};
struct STablet {
DYNLISTENER(Tip);
DYNLISTENER(Axis);
DYNLISTENER(Button);
DYNLISTENER(Proximity);
DYNLISTENER(Destroy);
wlr_tablet* wlrTablet = nullptr;
wlr_tablet_v2_tablet* wlrTabletV2 = nullptr;
wlr_input_device* wlrDevice = nullptr;
bool operator==(const STablet& b) {
return wlrDevice == b.wlrDevice;
}
};
struct STabletTool {
wlr_tablet_tool* wlrTabletTool = nullptr;
wlr_tablet_v2_tablet_tool* wlrTabletToolV2 = nullptr;
wlr_tablet_v2_tablet* wlrTabletOwnerV2 = nullptr;
wlr_surface* pSurface = nullptr;
double tiltX = 0;
double tiltY = 0;
bool active = true;
DYNLISTENER(TabletToolDestroy);
DYNLISTENER(TabletToolSetCursor);
bool operator==(const STabletTool& b) {
return wlrTabletTool == b.wlrTabletTool;
}
};
struct STabletPad {
wlr_tablet_v2_tablet_pad* wlrTabletPadV2 = nullptr;
STablet* pTabletParent = nullptr;
DYNLISTENER(Attach);
DYNLISTENER(Button);
DYNLISTENER(Strip);
DYNLISTENER(Ring);
DYNLISTENER(Destroy);
bool operator==(const STabletPad& b) {
return wlrTabletPadV2 == b.wlrTabletPadV2;
}
}; };

View File

@@ -57,7 +57,7 @@ void CWorkspace::startAnim(bool in, bool left, bool instant) {
m_fAlpha.setValueAndWarp(255.f); m_fAlpha.setValueAndWarp(255.f);
m_fAlpha = 0.f; m_fAlpha = 0.f;
} }
} else if ("slidevert") { } else if (ANIMSTYLE == "slidevert") {
// fallback is slide // fallback is slide
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID); const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);

View File

@@ -77,6 +77,9 @@ extern "C" {
#include "../wlroots/include/wlr/util/log.h" #include "../wlroots/include/wlr/util/log.h"
#include "../wlroots/include/wlr/xwayland.h" #include "../wlroots/include/wlr/xwayland.h"
#include "../wlroots/include/wlr/util/region.h" #include "../wlroots/include/wlr/util/region.h"
#include "../wlroots/include/wlr/types/wlr_tablet_pad.h"
#include "../wlroots/include/wlr/types/wlr_tablet_tool.h"
#include "../wlroots/include/wlr/types/wlr_tablet_v2.h"
#include <xkbcommon/xkbcommon.h> #include <xkbcommon/xkbcommon.h>
#include <X11/Xproto.h> #include <X11/Xproto.h>
#include "../wlroots/include/wlr/render/egl.h" #include "../wlroots/include/wlr/render/egl.h"

View File

@@ -164,10 +164,12 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode) {
if (PWORKSPACE->m_bIsSpecialWorkspace) { if (PWORKSPACE->m_bIsSpecialWorkspace) {
// if special, we adjust the coords a bit // if special, we adjust the coords a bit
PWINDOW->m_vRealPosition = calcPos + (calcSize - calcSize * 0.8f) / 2.f; static auto *const PSCALEFACTOR = &g_pConfigManager->getConfigValuePtr("dwindle:special_scale_factor")->floatValue;
PWINDOW->m_vRealSize = calcSize * 0.8f;
g_pXWaylandManager->setWindowSize(PWINDOW, calcSize * 0.8f); PWINDOW->m_vRealPosition = calcPos + (calcSize - calcSize * *PSCALEFACTOR) / 2.f;
PWINDOW->m_vRealSize = calcSize * *PSCALEFACTOR;
g_pXWaylandManager->setWindowSize(PWINDOW, calcSize * *PSCALEFACTOR);
} else { } else {
PWINDOW->m_vRealSize = calcSize; PWINDOW->m_vRealSize = calcSize;
PWINDOW->m_vRealPosition = calcPos; PWINDOW->m_vRealPosition = calcPos;
@@ -452,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) {
@@ -508,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();
} }
} }
@@ -599,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);

View File

@@ -48,6 +48,7 @@ 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*);

View File

@@ -49,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)

View File

@@ -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.

View File

@@ -23,20 +23,22 @@ void CAnimationManager::tick() {
bool animationsDisabled = false; bool animationsDisabled = false;
if (!g_pConfigManager->getInt("animations:enabled")) static auto *const PANIMENABLED = &g_pConfigManager->getConfigValuePtr("animations:enabled")->intValue;
if (!*PANIMENABLED)
animationsDisabled = true; animationsDisabled = true;
const float ANIMSPEED = g_pConfigManager->getFloat("animations:speed"); static auto *const PANIMSPEED = &g_pConfigManager->getConfigValuePtr("animations:speed")->floatValue;
const auto BORDERSIZE = g_pConfigManager->getInt("general:border_size"); static auto *const PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue;
const auto BEZIERSTR = g_pConfigManager->getString("animations:curve"); static auto *const BEZIERSTR = &g_pConfigManager->getConfigValuePtr("animations:curve")->strValue;
auto DEFAULTBEZIER = m_mBezierCurves.find(BEZIERSTR); auto DEFAULTBEZIER = m_mBezierCurves.find(*BEZIERSTR);
if (DEFAULTBEZIER == m_mBezierCurves.end()) if (DEFAULTBEZIER == m_mBezierCurves.end())
DEFAULTBEZIER = m_mBezierCurves.find("default"); DEFAULTBEZIER = m_mBezierCurves.find("default");
for (auto& av : m_lAnimatedVariables) { for (auto& av : m_lAnimatedVariables) {
// get speed // get speed
const auto SPEED = *av->m_pSpeed == 0 ? ANIMSPEED : *av->m_pSpeed; const auto SPEED = *av->m_pSpeed == 0 ? *PANIMSPEED : *av->m_pSpeed;
// window stuff // window stuff
const auto PWINDOW = (CWindow*)av->m_pWindow; const auto PWINDOW = (CWindow*)av->m_pWindow;
@@ -45,28 +47,13 @@ void CAnimationManager::tick() {
wlr_box WLRBOXPREV = {0,0,0,0}; wlr_box WLRBOXPREV = {0,0,0,0};
if (PWINDOW) { if (PWINDOW) {
WLRBOXPREV = {(int)PWINDOW->m_vRealPosition.vec().x - BORDERSIZE - 1, (int)PWINDOW->m_vRealPosition.vec().y - BORDERSIZE - 1, (int)PWINDOW->m_vRealSize.vec().x + 2 * BORDERSIZE + 2, (int)PWINDOW->m_vRealSize.vec().y + 2 * BORDERSIZE + 2}; WLRBOXPREV = {(int)PWINDOW->m_vRealPosition.vec().x - (int)*PBORDERSIZE - 1, (int)PWINDOW->m_vRealPosition.vec().y - (int)*PBORDERSIZE - 1, (int)PWINDOW->m_vRealSize.vec().x + 2 * (int)*PBORDERSIZE + 2, (int)PWINDOW->m_vRealSize.vec().y + 2 * (int)*PBORDERSIZE + 2};
} else if (PWORKSPACE) { } else if (PWORKSPACE) {
const auto PMONITOR = g_pCompositor->getMonitorFromID(PWORKSPACE->m_iMonitorID); const auto PMONITOR = g_pCompositor->getMonitorFromID(PWORKSPACE->m_iMonitorID);
WLRBOXPREV = {(int)PMONITOR->vecPosition.x, (int)PMONITOR->vecPosition.y, (int)PMONITOR->vecSize.x, (int)PMONITOR->vecSize.y}; WLRBOXPREV = {(int)PMONITOR->vecPosition.x, (int)PMONITOR->vecPosition.y, (int)PMONITOR->vecSize.x, (int)PMONITOR->vecSize.y};
} else if (PLAYER) { } else if (PLAYER) {
WLRBOXPREV = PLAYER->geometry; WLRBOXPREV = PLAYER->geometry;
} }
// check if it's disabled, if so, warp
if (av->m_pEnabled == 0 || animationsDisabled) {
av->warp();
g_pHyprRenderer->damageBox(&WLRBOXPREV);
if (PWINDOW) {
g_pHyprRenderer->damageWindow(PWINDOW);
// set size and pos if valid
if (g_pCompositor->windowValidMapped(PWINDOW))
g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goalv());
}
continue;
}
// beziers are with a switch unforto // beziers are with a switch unforto
// TODO: maybe do something cleaner // TODO: maybe do something cleaner
@@ -78,6 +65,13 @@ void CAnimationManager::tick() {
switch (av->m_eVarType) { switch (av->m_eVarType) {
case AVARTYPE_FLOAT: { case AVARTYPE_FLOAT: {
if (!deltazero(av->m_fValue, av->m_fGoal)) { if (!deltazero(av->m_fValue, av->m_fGoal)) {
// for disabled anims just warp
if (av->m_pEnabled == 0 || animationsDisabled) {
av->warp();
break;
}
const auto DELTA = av->m_fGoal - av->m_fBegun; const auto DELTA = av->m_fGoal - av->m_fBegun;
const auto BEZIER = m_mBezierCurves.find(*av->m_pBezier); const auto BEZIER = m_mBezierCurves.find(*av->m_pBezier);
@@ -96,6 +90,13 @@ void CAnimationManager::tick() {
} }
case AVARTYPE_VECTOR: { case AVARTYPE_VECTOR: {
if (!deltazero(av->m_vValue, av->m_vGoal)) { if (!deltazero(av->m_vValue, av->m_vGoal)) {
// for disabled anims just warp
if (av->m_pEnabled == 0 || animationsDisabled) {
av->warp();
break;
}
const auto DELTA = av->m_vGoal - av->m_vBegun; const auto DELTA = av->m_vGoal - av->m_vBegun;
const auto BEZIER = m_mBezierCurves.find(*av->m_pBezier); const auto BEZIER = m_mBezierCurves.find(*av->m_pBezier);
@@ -114,6 +115,13 @@ void CAnimationManager::tick() {
} }
case AVARTYPE_COLOR: { case AVARTYPE_COLOR: {
if (!deltazero(av->m_cValue, av->m_cGoal)) { if (!deltazero(av->m_cValue, av->m_cGoal)) {
// for disabled anims just warp
if (av->m_pEnabled == 0 || animationsDisabled) {
av->warp();
break;
}
const auto DELTA = av->m_cGoal - av->m_cBegun; const auto DELTA = av->m_cGoal - av->m_cBegun;
const auto BEZIER = m_mBezierCurves.find(*av->m_pBezier); const auto BEZIER = m_mBezierCurves.find(*av->m_pBezier);
@@ -152,8 +160,9 @@ void CAnimationManager::tick() {
RASSERT(PWINDOW, "Tried to AVARDAMAGE_BORDER a non-window AVAR!"); RASSERT(PWINDOW, "Tried to AVARDAMAGE_BORDER a non-window AVAR!");
// damage only the border. // damage only the border.
const auto BORDERSIZE = g_pConfigManager->getInt("general:border_size") + 1; // +1 for padding and shit static auto *const PROUNDING = &g_pConfigManager->getConfigValuePtr("decoration:rounding")->intValue;
const auto ROUNDINGSIZE = g_pConfigManager->getInt("decoration:rounding") + 1; const auto ROUNDINGSIZE = *PROUNDING + 1;
const auto BORDERSIZE = *PBORDERSIZE;
// damage for old box // damage for old box
g_pHyprRenderer->damageBox(WLRBOXPREV.x - BORDERSIZE, WLRBOXPREV.y - BORDERSIZE, WLRBOXPREV.width + 2 * BORDERSIZE, BORDERSIZE + ROUNDINGSIZE); // top g_pHyprRenderer->damageBox(WLRBOXPREV.x - BORDERSIZE, WLRBOXPREV.y - BORDERSIZE, WLRBOXPREV.width + 2 * BORDERSIZE, BORDERSIZE + ROUNDINGSIZE); // top

View File

@@ -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);

View File

@@ -1,5 +1,7 @@
#include "KeybindManager.hpp" #include "KeybindManager.hpp"
#include <regex>
CKeybindManager::CKeybindManager() { CKeybindManager::CKeybindManager() {
// initialize all dispatchers // initialize all dispatchers
@@ -24,6 +26,10 @@ CKeybindManager::CKeybindManager() {
m_mDispatchers["movecurrentworkspacetomonitor"] = moveCurrentWorkspaceToMonitor; m_mDispatchers["movecurrentworkspacetomonitor"] = moveCurrentWorkspaceToMonitor;
m_mDispatchers["moveworkspacetomonitor"] = moveWorkspaceToMonitor; m_mDispatchers["moveworkspacetomonitor"] = moveWorkspaceToMonitor;
m_mDispatchers["togglespecialworkspace"] = toggleSpecialWorkspace; m_mDispatchers["togglespecialworkspace"] = toggleSpecialWorkspace;
m_mDispatchers["forcerendererreload"] = forceRendererReload;
m_mDispatchers["resizeactive"] = resizeActive;
m_mDispatchers["cyclenext"] = circleNext;
m_mDispatchers["focuswindowbyclass"] = focusWindowByClass;
} }
void CKeybindManager::addKeybind(SKeybind kb) { void CKeybindManager::addKeybind(SKeybind kb) {
@@ -109,8 +115,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;
} }
@@ -337,14 +352,19 @@ 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; std::string unusedName;
const auto WORKSPACEID = getWorkspaceIDFromString(args, 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->getWorkspaceByID(WORKSPACEID); const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(WORKSPACEID);
@@ -397,6 +417,8 @@ void CKeybindManager::moveActiveToWorkspace(std::string args) {
for (auto& m : g_pCompositor->m_lMonitors) for (auto& m : g_pCompositor->m_lMonitors)
m.specialWorkspaceOpen = false; m.specialWorkspaceOpen = false;
} }
g_pInputManager->refocus();
} }
void CKeybindManager::moveActiveToWorkspaceSilent(std::string args) { void CKeybindManager::moveActiveToWorkspaceSilent(std::string args) {
@@ -453,6 +475,8 @@ void CKeybindManager::moveActiveToWorkspaceSilent(std::string args) {
POLDWORKSPACEONMON->m_fAlpha.setValueAndWarp(255.f); POLDWORKSPACEONMON->m_fAlpha.setValueAndWarp(255.f);
m_bSuppressWorkspaceChangeEvents = false; m_bSuppressWorkspaceChangeEvents = false;
g_pInputManager->refocus();
} }
void CKeybindManager::moveFocusTo(std::string args) { void CKeybindManager::moveFocusTo(std::string args) {
@@ -749,6 +773,8 @@ void CKeybindManager::moveCurrentWorkspaceToMonitor(std::string args) {
} }
void CKeybindManager::moveWorkspaceToMonitor(std::string args) { 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 workspace = args.substr(0, args.find_first_of(' '));
std::string monitor = args.substr(args.find_first_of(' ') + 1); std::string monitor = args.substr(args.find_first_of(' ') + 1);
@@ -821,4 +847,63 @@ void CKeybindManager::toggleSpecialWorkspace(std::string args) {
} }
g_pInputManager->refocus(); 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));
}
void CKeybindManager::circleNext(std::string) {
if (!g_pCompositor->windowValidMapped(g_pCompositor->m_pLastWindow))
return;
g_pCompositor->focusWindow(g_pCompositor->getNextWindowOnWorkspace(g_pCompositor->m_pLastWindow));
const auto MIDPOINT = g_pCompositor->m_pLastWindow->m_vRealPosition.goalv() + g_pCompositor->m_pLastWindow->m_vRealSize.goalv() / 2.f;
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr, MIDPOINT.x, MIDPOINT.y);
}
void CKeybindManager::focusWindowByClass(std::string clazz) {
std::regex classCheck(clazz);
for (auto& w : g_pCompositor->m_lWindows) {
const auto windowClass = g_pXWaylandManager->getAppIDClass(&w);
if (!std::regex_search(windowClass, classCheck))
continue;
Debug::log(LOG, "Focusing to window name: %s", w.m_szTitle.c_str());
changeworkspace(std::to_string(w.m_iWorkspaceID));
g_pCompositor->focusWindow(&w);
const auto MIDPOINT = w.m_vRealPosition.goalv() + w.m_vRealSize.goalv() / 2.f;
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr, MIDPOINT.x, MIDPOINT.y);
break;
}
}

View File

@@ -54,6 +54,10 @@ private:
static void moveCurrentWorkspaceToMonitor(std::string); static void moveCurrentWorkspaceToMonitor(std::string);
static void moveWorkspaceToMonitor(std::string); static void moveWorkspaceToMonitor(std::string);
static void toggleSpecialWorkspace(std::string); static void toggleSpecialWorkspace(std::string);
static void forceRendererReload(std::string);
static void resizeActive(std::string);
static void circleNext(std::string);
static void focusWindowByClass(std::string);
friend class CCompositor; friend class CCompositor;
}; };

View File

@@ -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) {
@@ -123,9 +126,10 @@ void CHyprXWaylandManager::setWindowSize(CWindow* pWindow, const Vector2D& size)
wlr_xwayland_surface_configure(pWindow->m_uSurface.xwayland, pWindow->m_vRealPosition.vec().x, pWindow->m_vRealPosition.vec().y, size.x, size.y); wlr_xwayland_surface_configure(pWindow->m_uSurface.xwayland, pWindow->m_vRealPosition.vec().x, pWindow->m_vRealPosition.vec().y, size.x, size.y);
else { else {
// I don't know if this is fucking correct, but the fucking idea of putting shadows into a window's surface is borderline criminal. // 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->surface->current.width - pWindow->m_uSurface.xdg->current.geometry.width;
const auto YDELTA = pWindow->m_uSurface.xdg->surface->current.height - pWindow->m_uSurface.xdg->current.geometry.height; 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); wlr_xdg_toplevel_set_size(pWindow->m_uSurface.xdg->toplevel, size.x - XDELTA, size.y - YDELTA);
} }
} }

View File

@@ -1,16 +1,17 @@
#include "InputManager.hpp" #include "InputManager.hpp"
#include "../Compositor.hpp" #include "../../Compositor.hpp"
void CInputManager::onMouseMoved(wlr_pointer_motion_event* e) { void CInputManager::onMouseMoved(wlr_pointer_motion_event* e) {
float sensitivity = g_pConfigManager->getFloat("general:sensitivity"); float sensitivity = g_pConfigManager->getFloat("general:sensitivity");
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);
} }
@@ -236,28 +237,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() {
@@ -285,9 +282,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);
@@ -330,6 +349,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);
} }
@@ -469,3 +499,23 @@ void CInputManager::constrainMouse(SMouse* pMouse, wlr_pointer_constraint_v1* co
void Events::listener_commitConstraint(void* owner, void* data) { void Events::listener_commitConstraint(void* owner, void* data) {
//g_pInputManager->recheckConstraint((SMouse*)owner); //g_pInputManager->recheckConstraint((SMouse*)owner);
} }
void CInputManager::updateCapabilities(wlr_input_device* pDev) {
// TODO: this is dumb
switch (pDev->type) {
case WLR_INPUT_DEVICE_KEYBOARD:
m_uiCapabilities |= WL_SEAT_CAPABILITY_KEYBOARD;
break;
case WLR_INPUT_DEVICE_POINTER:
m_uiCapabilities |= WL_SEAT_CAPABILITY_POINTER;
break;
case WLR_INPUT_DEVICE_TOUCH:
m_uiCapabilities |= WL_SEAT_CAPABILITY_TOUCH;
break;
default:
break;
}
wlr_seat_set_capabilities(g_pCompositor->m_sSeat.seat, m_uiCapabilities);
}

View File

@@ -1,9 +1,9 @@
#pragma once #pragma once
#include "../defines.hpp" #include "../../defines.hpp"
#include <list> #include <list>
#include "../helpers/WLClasses.hpp" #include "../../helpers/WLClasses.hpp"
#include "../Window.hpp" #include "../../Window.hpp"
class CInputManager { class CInputManager {
public: public:
@@ -28,6 +28,7 @@ public:
void setKeyboardLayout(); void setKeyboardLayout();
void updateDragIcon(); void updateDragIcon();
void updateCapabilities(wlr_input_device*);
// for dragging floating windows // for dragging floating windows
@@ -36,14 +37,28 @@ 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: // tablets
std::list<STablet> m_lTablets;
std::list<STabletTool> m_lTabletTools;
std::list<STabletPad> m_lTabletPads;
std::list<SKeyboard> m_lKeyboards; void newTabletTool(wlr_input_device*);
std::list<SMouse> m_lMice; void newTabletPad(wlr_input_device*);
void focusTablet(STablet*, wlr_tablet_tool*, bool motion = false);
SKeyboard* m_pActiveKeyboard = nullptr;
private:
uint32_t m_uiCapabilities = 0;
void mouseMoveUnified(uint32_t, bool refocus = false); void mouseMoveUnified(uint32_t, bool refocus = false);
STabletTool* ensureTabletToolPresent(wlr_tablet_tool*);
}; };
inline std::unique_ptr<CInputManager> g_pInputManager; inline std::unique_ptr<CInputManager> g_pInputManager;

View File

@@ -0,0 +1,229 @@
#include "InputManager.hpp"
#include "../../Compositor.hpp"
void CInputManager::newTabletTool(wlr_input_device* pDevice) {
const auto PNEWTABLET = &m_lTablets.emplace_back();
PNEWTABLET->wlrTablet = pDevice->tablet;
PNEWTABLET->wlrDevice = pDevice;
PNEWTABLET->wlrTabletV2 = wlr_tablet_create(g_pCompositor->m_sWLRTabletManager, g_pCompositor->m_sSeat.seat, pDevice);
PNEWTABLET->wlrTablet->data = PNEWTABLET;
Debug::log(LOG, "Attaching tablet to cursor!");
wlr_cursor_attach_input_device(g_pCompositor->m_sWLRCursor, pDevice);
PNEWTABLET->hyprListener_Destroy.initCallback(&pDevice->events.destroy, [](void* owner, void* data) {
const auto PTAB = (STablet*)owner;
g_pInputManager->m_lTablets.remove(*PTAB);
Debug::log(LOG, "Removed a tablet");
}, PNEWTABLET, "Tablet");
PNEWTABLET->hyprListener_Axis.initCallback(&pDevice->tablet->events.axis, [](void* owner, void* data) {
const auto EVENT = (wlr_tablet_tool_axis_event*)data;
const auto PTAB = (STablet*)owner;
switch (EVENT->tool->type) {
case WLR_TABLET_TOOL_TYPE_MOUSE:
wlr_cursor_move(g_pCompositor->m_sWLRCursor, PTAB->wlrDevice, EVENT->dx, EVENT->dy);
g_pInputManager->refocus();
break;
default:
double x = (EVENT->updated_axes & WLR_TABLET_TOOL_AXIS_X) ? EVENT->x : NAN;
double y = (EVENT->updated_axes & WLR_TABLET_TOOL_AXIS_Y) ? EVENT->y : NAN;
wlr_cursor_warp_absolute(g_pCompositor->m_sWLRCursor, PTAB->wlrDevice, x, y);
g_pInputManager->refocus();
break;
}
const auto PTOOL = g_pInputManager->ensureTabletToolPresent(EVENT->tool);
// TODO: this might be wrong
if (PTOOL->active) {
g_pInputManager->refocus();
g_pInputManager->focusTablet(PTAB, EVENT->tool, true);
}
if (EVENT->updated_axes & WLR_TABLET_TOOL_AXIS_PRESSURE)
wlr_tablet_v2_tablet_tool_notify_pressure(PTOOL->wlrTabletToolV2, EVENT->pressure);
if (EVENT->updated_axes & WLR_TABLET_TOOL_AXIS_DISTANCE)
wlr_tablet_v2_tablet_tool_notify_distance(PTOOL->wlrTabletToolV2, EVENT->distance);
if (EVENT->updated_axes & WLR_TABLET_TOOL_AXIS_ROTATION)
wlr_tablet_v2_tablet_tool_notify_rotation(PTOOL->wlrTabletToolV2, EVENT->rotation);
if (EVENT->updated_axes & WLR_TABLET_TOOL_AXIS_SLIDER)
wlr_tablet_v2_tablet_tool_notify_slider(PTOOL->wlrTabletToolV2, EVENT->slider);
if (EVENT->updated_axes & WLR_TABLET_TOOL_AXIS_WHEEL)
wlr_tablet_v2_tablet_tool_notify_wheel(PTOOL->wlrTabletToolV2, EVENT->wheel_delta, 0);
if (EVENT->updated_axes & WLR_TABLET_TOOL_AXIS_TILT_X)
PTOOL->tiltX = EVENT->tilt_x;
if (EVENT->updated_axes & WLR_TABLET_TOOL_AXIS_TILT_Y)
PTOOL->tiltY = EVENT->tilt_y;
if (EVENT->updated_axes & (WLR_TABLET_TOOL_AXIS_TILT_X | WLR_TABLET_TOOL_AXIS_TILT_Y))
wlr_tablet_v2_tablet_tool_notify_tilt(PTOOL->wlrTabletToolV2, PTOOL->tiltX, PTOOL->tiltY);
}, PNEWTABLET, "Tablet");
PNEWTABLET->hyprListener_Tip.initCallback(&pDevice->tablet->events.tip, [](void* owner, void* data) {
const auto EVENT = (wlr_tablet_tool_tip_event*)data;
const auto PTAB = (STablet*)owner;
const auto PTOOL = g_pInputManager->ensureTabletToolPresent(EVENT->tool);
// TODO: this might be wrong
if (EVENT->state == WLR_TABLET_TOOL_TIP_DOWN) {
g_pInputManager->refocus();
g_pInputManager->focusTablet(PTAB, EVENT->tool);
wlr_send_tablet_v2_tablet_tool_down(PTOOL->wlrTabletToolV2);
}
else {
wlr_send_tablet_v2_tablet_tool_up(PTOOL->wlrTabletToolV2);
}
}, PNEWTABLET, "Tablet");
PNEWTABLET->hyprListener_Button.initCallback(&pDevice->tablet->events.button, [](void* owner, void* data) {
const auto EVENT = (wlr_tablet_tool_button_event*)data;
const auto PTOOL = g_pInputManager->ensureTabletToolPresent(EVENT->tool);
wlr_tablet_v2_tablet_tool_notify_button(PTOOL->wlrTabletToolV2, (zwp_tablet_pad_v2_button_state)EVENT->button, (zwp_tablet_pad_v2_button_state)EVENT->state);
}, PNEWTABLET, "Tablet");
PNEWTABLET->hyprListener_Proximity.initCallback(&pDevice->tablet->events.proximity, [](void* owner, void* data) {
const auto EVENT = (wlr_tablet_tool_proximity_event*)data;
const auto PTAB = (STablet*)owner;
const auto PTOOL = g_pInputManager->ensureTabletToolPresent(EVENT->tool);
if (EVENT->state == WLR_TABLET_TOOL_PROXIMITY_OUT) {
PTOOL->active = false;
if (PTOOL->pSurface) {
wlr_tablet_v2_tablet_tool_notify_proximity_out(PTOOL->wlrTabletToolV2);
PTOOL->pSurface = nullptr;
}
} else {
PTOOL->active = true;
g_pInputManager->refocus();
g_pInputManager->focusTablet(PTAB, EVENT->tool);
}
}, PNEWTABLET, "Tablet");
}
STabletTool* CInputManager::ensureTabletToolPresent(wlr_tablet_tool* pTool) {
if (pTool->data == nullptr) {
const auto PTOOL = &m_lTabletTools.emplace_back();
Debug::log(LOG, "Creating tablet tool v2 for %x", pTool);
PTOOL->wlrTabletTool = pTool;
pTool->data = PTOOL;
PTOOL->wlrTabletToolV2 = wlr_tablet_tool_create(g_pCompositor->m_sWLRTabletManager, g_pCompositor->m_sSeat.seat, pTool);
PTOOL->hyprListener_TabletToolDestroy.initCallback(&pTool->events.destroy, [](void* owner, void* data) {
const auto PTOOL = (STabletTool*)owner;
PTOOL->wlrTabletTool->data = nullptr;
g_pInputManager->m_lTabletTools.remove(*PTOOL);
}, PTOOL, "Tablet Tool V1");
//TODO: set cursor request
}
return (STabletTool*)pTool->data;
}
void CInputManager::newTabletPad(wlr_input_device* pDevice) {
const auto PNEWPAD = &m_lTabletPads.emplace_back();
PNEWPAD->wlrTabletPadV2 = wlr_tablet_pad_create(g_pCompositor->m_sWLRTabletManager, g_pCompositor->m_sSeat.seat, pDevice);
PNEWPAD->hyprListener_Button.initCallback(&pDevice->tablet_pad->events.button, [](void* owner, void* data) {
const auto EVENT = (wlr_tablet_pad_button_event*)data;
const auto PPAD = (STabletPad*)owner;
wlr_tablet_v2_tablet_pad_notify_mode(PPAD->wlrTabletPadV2, EVENT->group, EVENT->mode, EVENT->time_msec);
wlr_tablet_v2_tablet_pad_notify_button(PPAD->wlrTabletPadV2, EVENT->button, EVENT->time_msec, (zwp_tablet_pad_v2_button_state)EVENT->state);
}, PNEWPAD, "Tablet Pad");
PNEWPAD->hyprListener_Strip.initCallback(&pDevice->tablet_pad->events.strip, [](void* owner, void* data) {
const auto EVENT = (wlr_tablet_pad_strip_event*)data;
const auto PPAD = (STabletPad*)owner;
wlr_tablet_v2_tablet_pad_notify_strip(PPAD->wlrTabletPadV2, EVENT->strip, EVENT->position, EVENT->source == WLR_TABLET_PAD_STRIP_SOURCE_FINGER, EVENT->time_msec);
}, PNEWPAD, "Tablet Pad");
PNEWPAD->hyprListener_Ring.initCallback(&pDevice->tablet_pad->events.strip, [](void* owner, void* data) {
const auto EVENT = (wlr_tablet_pad_ring_event*)data;
const auto PPAD = (STabletPad*)owner;
wlr_tablet_v2_tablet_pad_notify_ring(PPAD->wlrTabletPadV2, EVENT->ring, EVENT->position, EVENT->source == WLR_TABLET_PAD_RING_SOURCE_FINGER, EVENT->time_msec);
}, PNEWPAD, "Tablet Pad");
PNEWPAD->hyprListener_Attach.initCallback(&pDevice->tablet_pad->events.strip, [](void* owner, void* data) {
const auto TABLET = (wlr_tablet_tool*)data;
const auto PPAD = (STabletPad*)owner;
PPAD->pTabletParent = (STablet*)TABLET->data;
if (!PPAD->pTabletParent)
Debug::log(ERR, "tabletpad got attached to a nullptr tablet!! this might be bad.");
}, PNEWPAD, "Tablet Pad");
PNEWPAD->hyprListener_Destroy.initCallback(&pDevice->events.destroy, [](void* owner, void* data) {
const auto PPAD = (STabletPad*)owner;
g_pInputManager->m_lTabletPads.remove(*PPAD);
Debug::log(LOG, "Removed a tablet pad");
}, PNEWPAD, "Tablet Pad");
}
void CInputManager::focusTablet(STablet* pTab, wlr_tablet_tool* pTool, bool motion) {
const auto PTOOL = g_pInputManager->ensureTabletToolPresent(pTool);
if (const auto PWINDOW = g_pCompositor->m_pLastWindow; g_pCompositor->windowValidMapped(PWINDOW)) {
const auto CURSORPOS = g_pInputManager->getMouseCoordsInternal();
const auto LOCAL = CURSORPOS - PWINDOW->m_vRealPosition.goalv();
if (PTOOL->pSurface != g_pCompositor->m_pLastFocus)
wlr_tablet_v2_tablet_tool_notify_proximity_out(PTOOL->wlrTabletToolV2);
if (g_pCompositor->m_pLastFocus) {
PTOOL->pSurface = g_pCompositor->m_pLastFocus;
wlr_tablet_v2_tablet_tool_notify_proximity_in(PTOOL->wlrTabletToolV2, pTab->wlrTabletV2, g_pCompositor->m_pLastFocus);
}
if (motion)
wlr_tablet_v2_tablet_tool_notify_motion(PTOOL->wlrTabletToolV2, LOCAL.x, LOCAL.y);
} else {
if (PTOOL->pSurface)
wlr_tablet_v2_tablet_tool_notify_proximity_out(PTOOL->wlrTabletToolV2);
}
}

View File

@@ -264,11 +264,14 @@ void CHyprOpenGLImpl::renderRect(wlr_box* box, const CColor& col, int round) {
const auto BOTTOMRIGHT = Vector2D(box->width - round, box->height - round); const auto BOTTOMRIGHT = Vector2D(box->width - round, box->height - round);
const auto FULLSIZE = Vector2D(box->width, box->height); const auto FULLSIZE = Vector2D(box->width, box->height);
static auto *const PMULTISAMPLEEDGES = &g_pConfigManager->getConfigValuePtr("decoration:multisample_edges")->intValue;
// Rounded corners // Rounded corners
glUniform2f(glGetUniformLocation(m_shQUAD.program, "topLeft"), (float)TOPLEFT.x, (float)TOPLEFT.y); glUniform2f(glGetUniformLocation(m_shQUAD.program, "topLeft"), (float)TOPLEFT.x, (float)TOPLEFT.y);
glUniform2f(glGetUniformLocation(m_shQUAD.program, "bottomRight"), (float)BOTTOMRIGHT.x, (float)BOTTOMRIGHT.y); glUniform2f(glGetUniformLocation(m_shQUAD.program, "bottomRight"), (float)BOTTOMRIGHT.x, (float)BOTTOMRIGHT.y);
glUniform2f(glGetUniformLocation(m_shQUAD.program, "fullSize"), (float)FULLSIZE.x, (float)FULLSIZE.y); glUniform2f(glGetUniformLocation(m_shQUAD.program, "fullSize"), (float)FULLSIZE.x, (float)FULLSIZE.y);
glUniform1f(glGetUniformLocation(m_shQUAD.program, "radius"), round); glUniform1f(glGetUniformLocation(m_shQUAD.program, "radius"), round);
glUniform1i(glGetUniformLocation(m_shQUAD.program, "primitiveMultisample"), (int)(*PMULTISAMPLEEDGES == 1 && round != 0));
glVertexAttribPointer(m_shQUAD.posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts); glVertexAttribPointer(m_shQUAD.posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
glVertexAttribPointer(m_shQUAD.texAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts); glVertexAttribPointer(m_shQUAD.texAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
@@ -304,7 +307,7 @@ 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!");
@@ -356,12 +359,14 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_b
const auto TOPLEFT = Vector2D(round, round); const auto TOPLEFT = Vector2D(round, round);
const auto BOTTOMRIGHT = Vector2D(tex.m_vSize.x - round, tex.m_vSize.y - round); const auto BOTTOMRIGHT = Vector2D(tex.m_vSize.x - round, tex.m_vSize.y - round);
const auto FULLSIZE = tex.m_vSize; const auto FULLSIZE = tex.m_vSize;
static auto *const PMULTISAMPLEEDGES = &g_pConfigManager->getConfigValuePtr("decoration:multisample_edges")->intValue;
// Rounded corners // Rounded corners
glUniform2f(glGetUniformLocation(shader->program, "topLeft"), (float)TOPLEFT.x, (float)TOPLEFT.y); glUniform2f(glGetUniformLocation(shader->program, "topLeft"), (float)TOPLEFT.x, (float)TOPLEFT.y);
glUniform2f(glGetUniformLocation(shader->program, "bottomRight"), (float)BOTTOMRIGHT.x, (float)BOTTOMRIGHT.y); glUniform2f(glGetUniformLocation(shader->program, "bottomRight"), (float)BOTTOMRIGHT.x, (float)BOTTOMRIGHT.y);
glUniform2f(glGetUniformLocation(shader->program, "fullSize"), (float)FULLSIZE.x, (float)FULLSIZE.y); glUniform2f(glGetUniformLocation(shader->program, "fullSize"), (float)FULLSIZE.x, (float)FULLSIZE.y);
glUniform1f(glGetUniformLocation(shader->program, "radius"), round); glUniform1f(glGetUniformLocation(shader->program, "radius"), round);
glUniform1i(glGetUniformLocation(shader->program, "primitiveMultisample"), (int)(*PMULTISAMPLEEDGES == 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);
@@ -403,8 +408,9 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_b
// some other func might be using it. // some other func might be using it.
if (border) { if (border) {
auto BORDERCOL = m_pCurrentWindow->m_cRealBorderColor.col(); auto BORDERCOL = m_pCurrentWindow->m_cRealBorderColor.col();
static auto *const PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue;
BORDERCOL.a *= alpha / 255.f; BORDERCOL.a *= alpha / 255.f;
renderBorder(pBox, BORDERCOL, g_pConfigManager->getInt("general:border_size"), round); renderBorder(pBox, BORDERCOL, *PBORDERSIZE, round);
glStencilMask(-1); glStencilMask(-1);
glStencilFunc(GL_ALWAYS, 1, 0xFF); glStencilFunc(GL_ALWAYS, 1, 0xFF);
glDisable(GL_STENCIL_TEST); glDisable(GL_STENCIL_TEST);
@@ -432,14 +438,14 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, wlr_box* p
wlr_matrix_transpose(glMatrix, glMatrix); wlr_matrix_transpose(glMatrix, glMatrix);
// get the config settings // get the config settings
const auto BLURSIZE = g_pConfigManager->getInt("decoration:blur_size"); static auto *const PBLURSIZE = &g_pConfigManager->getConfigValuePtr("decoration:blur_size")->intValue;
const auto BLURPASSES = g_pConfigManager->getInt("decoration:blur_passes"); static auto *const PBLURPASSES = &g_pConfigManager->getConfigValuePtr("decoration:blur_passes")->intValue;
// prep damage // prep damage
pixman_region32_t damage; pixman_region32_t damage;
pixman_region32_init(&damage); pixman_region32_init(&damage);
pixman_region32_copy(&damage, originalDamage); pixman_region32_copy(&damage, originalDamage);
wlr_region_expand(&damage, &damage, pow(2, BLURPASSES) * BLURSIZE); wlr_region_expand(&damage, &damage, pow(2, *PBLURPASSES) * *PBLURSIZE);
// helper // helper
const auto PMIRRORFB = &m_mMonitorRenderResources[m_RenderData.pMonitor].mirrorFB; const auto PMIRRORFB = &m_mMonitorRenderResources[m_RenderData.pMonitor].mirrorFB;
@@ -464,7 +470,7 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, wlr_box* p
// prep two shaders // prep two shaders
glUniformMatrix3fv(pShader->proj, 1, GL_FALSE, glMatrix); glUniformMatrix3fv(pShader->proj, 1, GL_FALSE, glMatrix);
glUniform1f(glGetUniformLocation(pShader->program, "radius"), BLURSIZE * (a / 255.f)); // this makes the blursize change with a glUniform1f(glGetUniformLocation(pShader->program, "radius"), *PBLURSIZE * (a / 255.f)); // this makes the blursize change with a
if (pShader == &m_shBLUR1) if (pShader == &m_shBLUR1)
glUniform2f(glGetUniformLocation(m_shBLUR1.program, "halfpixel"), 0.5f / (m_RenderData.pMonitor->vecPixelSize.x / 2.f), 0.5f / (m_RenderData.pMonitor->vecPixelSize.y / 2.f)); glUniform2f(glGetUniformLocation(m_shBLUR1.program, "halfpixel"), 0.5f / (m_RenderData.pMonitor->vecPixelSize.x / 2.f), 0.5f / (m_RenderData.pMonitor->vecPixelSize.y / 2.f));
else else
@@ -508,12 +514,12 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, wlr_box* p
drawPass(&m_shBLUR1, &tempDamage); drawPass(&m_shBLUR1, &tempDamage);
// and draw // and draw
for (int i = 1; i < BLURPASSES; ++i) { for (int i = 1; i < *PBLURPASSES; ++i) {
wlr_region_scale(&tempDamage, &damage, 1.f / (1 << (i + 1))); wlr_region_scale(&tempDamage, &damage, 1.f / (1 << (i + 1)));
drawPass(&m_shBLUR1, &tempDamage); // down drawPass(&m_shBLUR1, &tempDamage); // down
} }
for (int i = BLURPASSES - 1; i >= 0; --i) { for (int i = *PBLURPASSES - 1; i >= 0; --i) {
wlr_region_scale(&tempDamage, &damage, 1.f / (1 << i)); // when upsampling we make the region twice as big wlr_region_scale(&tempDamage, &damage, 1.f / (1 << i)); // when upsampling we make the region twice as big
drawPass(&m_shBLUR2, &tempDamage); // up drawPass(&m_shBLUR2, &tempDamage); // up
} }
@@ -533,7 +539,9 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, wlr_box* p
void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, wlr_box* pBox, float a, wlr_surface* pSurface, int round, bool border) { void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, wlr_box* pBox, float a, wlr_surface* pSurface, int round, bool border) {
RASSERT(m_RenderData.pMonitor, "Tried to render texture with blur without begin()!"); RASSERT(m_RenderData.pMonitor, "Tried to render texture with blur without begin()!");
if (g_pConfigManager->getInt("decoration:blur") == 0) { static auto *const PBLURENABLED = &g_pConfigManager->getConfigValuePtr("decoration:blur")->intValue;
if (*PBLURENABLED == 0) {
renderTexture(tex, pBox, a, round, false, border); renderTexture(tex, pBox, a, round, false, border);
return; return;
} }
@@ -556,8 +564,10 @@ void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, wlr_box* pBox,
pixman_region32_copy(&inverseOpaque, &damage); pixman_region32_copy(&inverseOpaque, &damage);
} }
if (!pixman_region32_not_empty(&damage)) if (!pixman_region32_not_empty(&inverseOpaque)) {
return; // if its empty, reject. renderTexture(tex, pBox, a, round, false, border); // reject blurring a fully opaque window
return;
}
// blur the main FB, it will be rendered onto the mirror // blur the main FB, it will be rendered onto the mirror
const auto POUTFB = blurMainFramebufferWithDamage(a, pBox, &inverseOpaque); const auto POUTFB = blurMainFramebufferWithDamage(a, pBox, &inverseOpaque);
@@ -588,7 +598,8 @@ void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, wlr_box* pBox,
wlr_box MONITORBOX = {0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y}; wlr_box MONITORBOX = {0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y};
if (pixman_region32_not_empty(&damage)) { if (pixman_region32_not_empty(&damage)) {
// render our great blurred FB // render our great blurred FB
renderTextureInternalWithDamage(POUTFB->m_cTex, &MONITORBOX, g_pConfigManager->getInt("decoration:blur_ignore_opacity") ? 255.f : a, &damage); static auto *const PBLURIGNOREOPACITY = &g_pConfigManager->getConfigValuePtr("decoration:blur_ignore_opacity")->intValue;
renderTextureInternalWithDamage(POUTFB->m_cTex, &MONITORBOX, *PBLURIGNOREOPACITY ? 255.f : a, &damage);
// render the window, but clear stencil // render the window, but clear stencil
glClearStencil(0); glClearStencil(0);
@@ -598,7 +609,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);
@@ -612,7 +623,8 @@ void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, wlr_box* pBox,
} else { } else {
auto BORDERCOL = m_pCurrentWindow->m_cRealBorderColor.col(); auto BORDERCOL = m_pCurrentWindow->m_cRealBorderColor.col();
BORDERCOL.a *= a / 255.f; BORDERCOL.a *= a / 255.f;
renderBorder(pBox, BORDERCOL, g_pConfigManager->getInt("general:border_size"), round); static auto *const PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue;
renderBorder(pBox, BORDERCOL, *PBORDERSIZE, round);
} }
glDisable(GL_STENCIL_TEST); glDisable(GL_STENCIL_TEST);

View File

@@ -110,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);
}; };

View File

@@ -19,7 +19,9 @@ void renderSurface(struct wlr_surface* surface, int x, int y, void* data) {
} }
scaleBox(&windowBox, RDATA->output->scale); scaleBox(&windowBox, RDATA->output->scale);
float rounding = RDATA->dontRound ? 0 : RDATA->rounding == -1 ? g_pConfigManager->getInt("decoration:rounding") : RDATA->rounding; static auto *const PROUNDING = &g_pConfigManager->getConfigValuePtr("decoration:rounding")->intValue;
float rounding = RDATA->dontRound ? 0 : RDATA->rounding == -1 ? *PROUNDING : RDATA->rounding;
if (RDATA->surface && surface == RDATA->surface) if (RDATA->surface && surface == RDATA->surface)
g_pHyprOpenGL->renderTextureWithBlur(TEXTURE, &windowBox, RDATA->fadeAlpha * RDATA->alpha, surface, rounding, RDATA->decorate); g_pHyprOpenGL->renderTextureWithBlur(TEXTURE, &windowBox, RDATA->fadeAlpha * RDATA->alpha, surface, rounding, RDATA->decorate);
@@ -533,7 +535,9 @@ void CHyprRenderer::damageSurface(wlr_surface* pSurface, double x, double y) {
pixman_region32_fini(&damageBox); pixman_region32_fini(&damageBox);
if (g_pConfigManager->getInt("debug:log_damage")) static auto *const PLOGDAMAGE = &g_pConfigManager->getConfigValuePtr("debug:log_damage")->intValue;
if (*PLOGDAMAGE)
Debug::log(LOG, "Damage: Surface (extents): xy: %d, %d wh: %d, %d", damageBox.extents.x1, damageBox.extents.y1, damageBox.extents.x2 - damageBox.extents.x1, damageBox.extents.y2 - damageBox.extents.y1); Debug::log(LOG, "Damage: Surface (extents): xy: %d, %d wh: %d, %d", damageBox.extents.x1, damageBox.extents.y1, damageBox.extents.x2 - damageBox.extents.x1, damageBox.extents.y2 - damageBox.extents.y1);
} }
@@ -551,12 +555,14 @@ void CHyprRenderer::damageWindow(CWindow* pWindow) {
wlr_output_damage_add_box(m.damage, &fixedDamageBox); wlr_output_damage_add_box(m.damage, &fixedDamageBox);
} }
if (g_pConfigManager->getInt("debug:log_damage")) static auto *const PLOGDAMAGE = &g_pConfigManager->getConfigValuePtr("debug:log_damage")->intValue;
if (*PLOGDAMAGE)
Debug::log(LOG, "Damage: Window floated (%s): xy: %d, %d wh: %d, %d", pWindow->m_szTitle.c_str(), damageBox.x, damageBox.y, damageBox.width, damageBox.height); Debug::log(LOG, "Damage: Window floated (%s): xy: %d, %d wh: %d, %d", pWindow->m_szTitle.c_str(), damageBox.x, damageBox.y, damageBox.width, damageBox.height);
} else { } else {
// damage by real size & pos + border size * 2 (JIC) // damage by real size & pos + border size * 2 (JIC)
const auto BORDERSIZE = g_pConfigManager->getInt("general:border_size"); static auto *const PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue;
wlr_box damageBox = { pWindow->m_vRealPosition.vec().x - BORDERSIZE - 1, pWindow->m_vRealPosition.vec().y - BORDERSIZE - 1, pWindow->m_vRealSize.vec().x + 2 * BORDERSIZE + 2, pWindow->m_vRealSize.vec().y + 2 * BORDERSIZE + 2}; wlr_box damageBox = { pWindow->m_vRealPosition.vec().x - *PBORDERSIZE - 1, pWindow->m_vRealPosition.vec().y - *PBORDERSIZE - 1, pWindow->m_vRealSize.vec().x + 2 * *PBORDERSIZE + 2, pWindow->m_vRealSize.vec().y + 2 * *PBORDERSIZE + 2};
for (auto& m : g_pCompositor->m_lMonitors) { for (auto& m : g_pCompositor->m_lMonitors) {
wlr_box fixedDamageBox = damageBox; wlr_box fixedDamageBox = damageBox;
fixedDamageBox.x -= m.vecPosition.x; fixedDamageBox.x -= m.vecPosition.x;
@@ -565,7 +571,9 @@ void CHyprRenderer::damageWindow(CWindow* pWindow) {
wlr_output_damage_add_box(m.damage, &fixedDamageBox); wlr_output_damage_add_box(m.damage, &fixedDamageBox);
} }
if (g_pConfigManager->getInt("debug:log_damage")) static auto *const PLOGDAMAGE = &g_pConfigManager->getConfigValuePtr("debug:log_damage")->intValue;
if (*PLOGDAMAGE)
Debug::log(LOG, "Damage: Window tiled (%s): xy: %d, %d wh: %d, %d", pWindow->m_szTitle.c_str(), damageBox.x, damageBox.y, damageBox.width, damageBox.height); Debug::log(LOG, "Damage: Window tiled (%s): xy: %d, %d wh: %d, %d", pWindow->m_szTitle.c_str(), damageBox.x, damageBox.y, damageBox.width, damageBox.height);
} }
} }
@@ -574,7 +582,9 @@ void CHyprRenderer::damageMonitor(SMonitor* pMonitor) {
wlr_box damageBox = {0, 0, pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y}; wlr_box damageBox = {0, 0, pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y};
wlr_output_damage_add_box(pMonitor->damage, &damageBox); wlr_output_damage_add_box(pMonitor->damage, &damageBox);
if (g_pConfigManager->getInt("debug:log_damage")) static auto *const PLOGDAMAGE = &g_pConfigManager->getConfigValuePtr("debug:log_damage")->intValue;
if (*PLOGDAMAGE)
Debug::log(LOG, "Damage: Monitor %s", pMonitor->szName.c_str()); Debug::log(LOG, "Damage: Monitor %s", pMonitor->szName.c_str());
} }
@@ -585,7 +595,9 @@ void CHyprRenderer::damageBox(wlr_box* pBox) {
wlr_output_damage_add_box(m.damage, &damageBox); wlr_output_damage_add_box(m.damage, &damageBox);
} }
if (g_pConfigManager->getInt("debug:log_damage")) static auto *const PLOGDAMAGE = &g_pConfigManager->getConfigValuePtr("debug:log_damage")->intValue;
if (*PLOGDAMAGE)
Debug::log(LOG, "Damage: Box: xy: %d, %d wh: %d, %d", pBox->x, pBox->y, pBox->width, pBox->height); Debug::log(LOG, "Damage: Box: xy: %d, %d wh: %d, %d", pBox->x, pBox->y, pBox->width, pBox->height);
} }
@@ -717,5 +729,5 @@ void CHyprRenderer::applyMonitorRule(SMonitor* pMonitor, SMonitorRule* pMonitorR
arrangeLayersForMonitor(pMonitor->ID); arrangeLayersForMonitor(pMonitor->ID);
// frame skip // frame skip
pMonitor->needsFrameSkip = true; pMonitor->framesToSkip = 1;
} }

View File

@@ -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;
})#"; })#";

Submodule wlroots updated: 75d31509db...b89ed9015c