Compare commits

..

127 Commits

Author SHA1 Message Date
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
vaxerski
970018248f Don't damage surfaces coming from not rendered windows 2022-05-31 22:16:13 +02: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
vaxerski
471654d791 remove monitor recommended dt from config 2022-05-31 21:05:46 +02:00
vaxerski
679e36d82e fix border size on scaled outputs 2022-05-31 20:38:45 +02:00
vaxerski
0f8712ed64 fix crash in moveWorkspaceToMonitor 2022-05-31 18:47:32 +02:00
vaxerski
3e28a8b690 added slidevert for workspaces 2022-05-31 17:56:33 +02:00
vaxerski
8de7cc5a8d opacity windowrule support 2 values 2022-05-31 17:35:50 +02:00
vaxerski
e73df80782 Add mon in mon out events and fix crash 2022-05-31 17:17:44 +02:00
vaxerski
0d7131d30e fix typo in hyprctl clients and activewindow 2022-05-31 16:52:28 +02:00
vaxerski
d2e0b7c22a render special over fullscreen 2022-05-31 14:20:41 +02:00
vaxerski
c1193ee483 updated readme features 2022-05-31 14:15:28 +02:00
vaxerski
042e79b888 fix fatal crash 2022-05-31 14:04:11 +02:00
vaxerski
0055efc4f1 Added a special workspace 2022-05-31 14:01:00 +02:00
vaxerski
df722cbb86 Added relative monitor workspace offset 2022-05-31 12:33:08 +02:00
vaxerski
68f7e565e6 Use existing default mon workspace if available on connect 2022-05-31 12:10:34 +02:00
vaxerski
48a3b1c514 fix oopsie 2022-05-31 11:02:54 +02:00
vaxerski
85128ebb7d Merge pull request #130 from vaxerski/bundle-wlroots
Bundle wlroots
2022-05-31 10:50:55 +02:00
vaxerski
ad98b96891 add submodules to CI 2022-05-31 10:47:56 +02:00
vaxerski
2e7586e841 fix up config and includes 2022-05-31 10:43:41 +02:00
vaxerski
f6ba9909d6 added submodule 2022-05-31 10:08:57 +02:00
vaxerski
c9041bf5c9 notify workspace protocol of workspace group change 2022-05-30 20:51:45 +02:00
vaxerski
b2474d406a don't duplicate workspaces on connect 2022-05-30 20:45:39 +02:00
vaxerski
eee9698ec9 move workspaces and not windows on mon disconnect 2022-05-30 20:44:14 +02:00
vaxerski
1f4c938c67 Added moving workspaces 2022-05-30 20:05:38 +02:00
vaxerski
c44c79abb2 fix monitor cleanups on removed 2022-05-30 17:11:35 +02:00
vaxerski
1e096f6fcd fix moveactivetoworkspace 2022-05-30 15:28:23 +02:00
vaxerski
b1c11f3d2e consider the full bb with deco in rendering 2022-05-30 14:55:42 +02:00
vaxerski
da63503d5f updated issue templates
dont submit aur coredumps plox
2022-05-30 14:21:33 +02:00
vaxerski
7167be9c48 Fix relative IDs in movetoworkspace crashing 2022-05-30 14:18:46 +02:00
vaxerski
e81790f357 massive oopsie in logs 2022-05-30 14:12:36 +02:00
vaxerski
edf57c50ff use exit in default config 2022-05-30 09:22:06 +02:00
vaxerski
e2be91582a use exit in example conf 2022-05-30 09:21:39 +02:00
vaxerski
7522ade58d don't set fullscreen to maximized apps 2022-05-30 09:18:05 +02:00
vaxerski
3d7abfea92 Log keybind dispatchers only 2022-05-30 09:16:00 +02:00
vaxerski
2de65771ea ignore .tar.gz 2022-05-29 22:01:16 +02:00
vaxerski
6b60595822 ffs i committed this 2022-05-29 22:00:57 +02:00
vaxerski
b76b32b458 don't add existing and invalid monitors 2022-05-29 20:15:34 +02:00
vaxerski
f5645805d8 Don't animate out if window wasnt animated in 2022-05-29 16:01:45 +02:00
vaxerski
15338fcf63 Merge pull request #122 from vaxerski/transforms
Added monitor transforms
2022-05-29 15:48:04 +02:00
vaxerski
227cbb0464 Added fullscreen types, maximize and full 2022-05-29 15:45:51 +02:00
vaxerski
9842730f57 Added fullscreen types, maximize and full 2022-05-29 15:44:30 +02:00
vaxerski
d0ff0c0990 Added basic monitor transforms, has bugs
blur doesnt work on transformed outputs
full damage tracking issues
2022-05-29 12:27:45 +02:00
vaxerski
fdb3f610e5 Added wlr_foreign_toplevel_v1 2022-05-29 11:24:42 +02:00
vaxerski
d2e1899f26 Merge pull request #119 from ThatOneCalculator/main
Update AUR PKGBUILDs
2022-05-29 09:09:17 +02:00
Kainoa Kanter
9d3099b21f Update PKGBUILD 2022-05-28 18:08:22 -07:00
Kainoa Kanter
4cc085ac75 Update PKGBUILD-git 2022-05-28 18:07:28 -07:00
Kainoa Kanter
af55d5aa96 Create PKGBUILD 2022-05-28 18:06:18 -07:00
vaxerski
632d00c51c [gha] bump flake inputs 2022-05-29 00:45:53 +00:00
vaxerski
f06d4fca27 Fix one more SIGSEGV while exiting 2022-05-29 00:07:31 +02:00
vaxerski
2cd5059cf1 ignore gmon.out 2022-05-29 00:04:16 +02:00
vaxerski
65610555c4 gfd i committed gmon 2022-05-29 00:03:42 +02:00
vaxerski
3f8845a6a7 Added an exit dispatcher and no more SIGSEGV on exit 2022-05-29 00:00:47 +02:00
vaxerski
894ae2d742 Use C++-styled pointers for decorations 2022-05-28 23:43:11 +02:00
vaxerski
08e0567d3a fix typo in GDK offset adjustments 2022-05-28 20:54:15 +02:00
vaxerski
685cf1e00d remove unused PMONITOR var 2022-05-28 20:50:50 +02:00
vaxerski
bdf1c16195 Added IHyprWindowDecoration and Group Bars 2022-05-28 20:46:20 +02:00
vaxerski
b1b24cb21a Added changegroupactive direction 2022-05-28 19:16:20 +02:00
vaxerski
9ede0f1c7d Added blur_ignore_opacity 2022-05-28 18:57:32 +02:00
vaxerski
10a9325a6a Fix buggy slide out on multimon 2022-05-28 18:52:22 +02:00
vaxerski
e4d494aed4 fix focusmonitor with named workspaces 2022-05-28 18:38:49 +02:00
vaxerski
5c911df351 Fix closing anims on multimon 2022-05-28 18:33:47 +02:00
vaxerski
15553804d6 Added closing animations (reverse of open) 2022-05-28 18:28:55 +02:00
vaxerski
7f1f14fe85 Added a rounding rule 2022-05-28 17:48:01 +02:00
vaxerski
7d442d4851 Added rendertime no overlay 2022-05-28 17:40:57 +02:00
vaxerski
8c10857f14 Added a debug overlay 2022-05-28 17:32:19 +02:00
vaxerski
9b6960eb55 fix calculating stupid gdk surface offsets 2022-05-27 21:10:51 +02:00
vaxerski
4cda50399c [gha] bump flake inputs 2022-05-27 14:06:54 +00:00
vaxerski
daff7d8ca2 use xdg-shell v3 2022-05-27 16:05:25 +02:00
vaxerski
1bef63a1e6 fix for latest wlroots 2022-05-27 16:03:24 +02:00
72 changed files with 2428 additions and 586 deletions

View File

@@ -3,13 +3,10 @@ name: Bug report
about: Found a bug? Report it here! about: Found a bug? Report it here!
title: '' title: ''
labels: bug labels: bug
assignees: ''
--- ---
**Describe the bug** Please consult the issue guidelines at
https://github.com/vaxerski/Hyprland/blob/main/docs/ISSUE_GUIDELINES.md
BEFORE submitting.
**Images/videos/anything that would help**
Please attach a log (it's in /tmp/hypr/hyprland.log) and, if crashing, a crashdump (coredumpctl, then coredumpctl info <pid>)

View File

@@ -3,7 +3,10 @@ name: Feature request
about: Suggest a feature/change/idea about: Suggest a feature/change/idea
title: '' title: ''
labels: enhancement labels: enhancement
assignees: ''
--- ---
**Describe in detail your idea.** Please consult the issue guidelines at
https://github.com/vaxerski/Hyprland/blob/main/docs/ISSUE_GUIDELINES.md
BEFORE submitting.

View File

@@ -30,6 +30,8 @@ jobs:
- name: Checkout Hyprland - name: Checkout Hyprland
uses: actions/checkout@v3 uses: actions/checkout@v3
with:
submodules: recursive
- name: Build Hyprland With default settings - name: Build Hyprland With default settings
run: | run: |

View File

@@ -8,6 +8,8 @@ jobs:
steps: steps:
- name: Clone repository - name: Clone repository
uses: actions/checkout@v3 uses: actions/checkout@v3
with:
submodules: recursive
- name: Install nix - name: Install nix
uses: cachix/install-nix-action@v17 uses: cachix/install-nix-action@v17
with: with:

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"

4
.gitignore vendored
View File

@@ -19,3 +19,7 @@ result
.ccls-cache .ccls-cache
hyprctl/hyprctl hyprctl/hyprctl
gmon.out
*.out
*.tar.gz

3
.gitmodules vendored Normal file
View File

@@ -0,0 +1,3 @@
[submodule "wlroots"]
path = wlroots
url = https://gitlab.freedesktop.org/wlroots/wlroots

View File

@@ -89,6 +89,7 @@ clear:
rm -rf build rm -rf build
rm -f *.o *-protocol.h *-protocol.c rm -f *.o *-protocol.h *-protocol.c
rm -f ./hyprctl/hyprctl rm -f ./hyprctl/hyprctl
rm -rf ./wlroots/build
all: all:
make config make config
@@ -113,4 +114,16 @@ uninstall:
rm -f ${PREFIX}/bin/hyprctl rm -f ${PREFIX}/bin/hyprctl
rm -rf ${PREFIX}/share/hyprland rm -rf ${PREFIX}/share/hyprland
config: xdg-shell-protocol.o wlr-layer-shell-unstable-v1-protocol.o wlr-screencopy-unstable-v1-protocol.o idle-protocol.o ext-workspace-unstable-v1-protocol.o pointer-constraints-unstable-v1-protocol.o protocols: xdg-shell-protocol.o wlr-layer-shell-unstable-v1-protocol.o wlr-screencopy-unstable-v1-protocol.o idle-protocol.o ext-workspace-unstable-v1-protocol.o pointer-constraints-unstable-v1-protocol.o
config:
make protocols
sed -i -E 's/(soversion = 11)([^032]|$$)/soversion = 11032/g' ./wlroots/meson.build
rm -rf ./wlroots/build
cd wlroots && meson ./build --prefix=/usr --buildtype=release
cd wlroots && ninja -C build/
cd wlroots && sudo ninja -C build/ install

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
@@ -51,17 +50,20 @@ Try it out and report bugs / suggestions!
- Easily expandable and readable codebase - Easily expandable and readable codebase
- Config reloaded instantly upon saving - Config reloaded instantly upon saving
- Bezier-curve window animations
- Custom bezier curve based animations - Custom bezier curve based animations
- Workspaces protocol support - wlr_ext workspaces protocol support
- Dual Kawase blur - Dual Kawase blur
- Window fade in / out - Fully dynamic workspaces
- Closely follows wlroots-git
- Bundled wlroots
- Window / layer fade in / out
- Tiling/floating/fullscreen windows - Tiling/floating/fullscreen windows
- Special Workspace (Scratchpad)
- Window/monitor rules - Window/monitor rules
- Socket-based IPC - Socket-based IPC
- Event System for bash scripts
- Rounded corners - Rounded corners
- Damage tracking(*Experimental*) - Full Damage tracking
- Moving/resizing
- Docks support - Docks support
<br> <br>

71
aur/PKGBUILD Normal file
View File

@@ -0,0 +1,71 @@
# Maintainer: ThatOneCalculator <kainoa@t1c.dev>
_pkgname="hyprland"
pkgname="${_pkgname}"
pkgver="0.3.0beta"
pkgrel=2
pkgdesc="Hyprland is a dynamic tiling Wayland compositor based on wlroots that doesn't sacrifice on its looks."
arch=(any)
url="https://github.com/vaxerski/Hyprland"
license=('BSD')
depends=(
libxcb
xcb-proto
xcb-util
xcb-util-keysyms
libxfixes
libx11
libxcomposite
xorg-xinput
libxrender
pixman
wayland-protocols
cairo
pango
polkit
glslang
libinput
libxcb
libxkbcommon
opengl-driver
pixman
wayland
xcb-util-errors
xcb-util-renderutil
xcb-util-wm
seatd
vulkan-icd-loader
vulkan-validation-layers
xorg-xwayland)
makedepends=(
git
cmake
ninja
gcc
gdb
meson
vulkan-headers
wayland-protocols
xorgproto)
source=("${pkgname}-${pkgver}.tar.gz::https://github.com/vaxerski/hyprland/archive/v${pkgver}.tar.gz")
sha256sums=('46ba9b61570f3385673dfd27a3d1dc5a084236f138bca1c2537335e0cdce9e78')
conflicts=("${_pkgname}-git" "${_pkgname}" "${_pkgname}-bin")
options=(!makeflags !buildflags)
build() {
cd "$srcdir/Hyprland-$pkgver"
git submodule update --init
make all
}
package() {
cd "$srcdir/Hyprland-$pkgver"
mkdir -p "${pkgdir}/usr/share/wayland-sessions"
mkdir -p "${pkgdir}/usr/share/hyprland"
install -Dm755 build/Hyprland -t "${pkgdir}/usr/bin"
install -Dm755 hyprctl/hyprctl -t "${pkgdir}/usr/bin"
install -Dm644 assets/*.png -t "${pkgdir}/usr/share/hyprland"
install -Dm644 example/hyprland.desktop -t "${pkgdir}/usr/share/wayland-sessions"
install -Dm644 example/hyprland.conf -t "${pkgdir}/usr/share/hyprland"
install -Dm644 LICENSE -t "${pkgdir}/usr/share/licenses/${_pkgname}"
}

55
aur/PKGBUILD-bin Normal file
View File

@@ -0,0 +1,55 @@
# Maintainer: ThatOneCalculator <kainoa@t1c.dev>
_pkgname="hyprland"
pkgname="${_pkgname}-bin"
pkgver="0.3.0beta"
pkgrel=2
pkgdesc="Hyprland is a dynamic tiling Wayland compositor based on wlroots that doesn't sacrifice on its looks."
arch=(any)
url="https://github.com/vaxerski/Hyprland"
license=('BSD')
depends=(
libxcb
xcb-proto
xcb-util
xcb-util-keysyms
libxfixes
libx11
libxcomposite
xorg-xinput
libxrender
pixman
wayland-protocols
cairo
pango
polkit
glslang
libinput
libxcb
libxkbcommon
opengl-driver
pixman
wayland
xcb-util-errors
xcb-util-renderutil
xcb-util-wm
seatd
vulkan-icd-loader
vulkan-validation-layers
xorg-xwayland)
source=("${pkgname}-${pkgver}.tar.gz::https://github.com/vaxerski/Hyprland/releases/download/v${pkgver}/v${pkgver}.tar.gz")
sha256sums=('46ba9b61570f3385673dfd27a3d1dc5a084236f138bca1c2537335e0cdce9e78')
conflicts=("${_pkgname}-git" "${_pkgname}" "${_pkgname}-bin")
package() {
cd "$srcdir/Hyprland-$pkgver"
mkdir -p "${pkgdir}/usr/share/wayland-sessions"
mkdir -p "${pkgdir}/usr/share/hyprland"
install -Dm755 ./Hyprland -t "${pkgdir}/usr/bin"
install -Dm755 ./hyprctl -t "${pkgdir}/usr/bin"
install -Dm755 ./libwlroots.so.11032 -t "${pkgdir}/usr/lib"
install -Dm644 assets/*.png -t "${pkgdir}/usr/share/hyprland"
install -Dm644 example/hyprland.desktop -t "${pkgdir}/usr/share/wayland-sessions"
install -Dm644 example/hyprland.conf -t "${pkgdir}/usr/share/hyprland"
install -Dm644 LICENSE -t "${pkgdir}/usr/share/licenses/${_pkgname}"
}

View File

@@ -1,16 +1,54 @@
# Maintainer: Sander van Kasteel <info@sandervankasteel.nl>, ThatOneCalculator <kainoa@t1c.dev> # Maintainer: ThatOneCalculator <kainoa@t1c.dev>, Sander van Kasteel <info@sandervankasteel.nl>
_pkgname="hyprland" _pkgname="hyprland"
pkgname="${_pkgname}-git" pkgname="${_pkgname}-git"
pkgver=r461.96cdf8f pkgver=r655.gef85544
pkgrel=5 pkgrel=1
pkgdesc="Hyprland is a dynamic tiling Wayland compositor based on wlroots that doesn't sacrifice on its looks." pkgdesc="Hyprland is a dynamic tiling Wayland compositor based on wlroots that doesn't sacrifice on its looks."
arch=(any) arch=(any)
url="https://github.com/vaxerski/Hyprland" url="https://github.com/vaxerski/Hyprland"
license=('BSD') license=('BSD')
depends=(libxcb xcb-proto xcb-util xcb-util-keysyms libxfixes libx11 libxcomposite xorg-xinput libxrender pixman wayland-protocols wlroots-git cairo pango) depends=(
makedepends=(git cmake ninja gcc gdb) libxcb
xcb-proto
xcb-util
xcb-util-keysyms
libxfixes
libx11
libxcomposite
xorg-xinput
libxrender
pixman
wayland-protocols
cairo
pango
polkit
glslang
libinput
libxcb
libxkbcommon
opengl-driver
pixman
wayland
xcb-util-errors
xcb-util-renderutil
xcb-util-wm
seatd
vulkan-icd-loader
vulkan-validation-layers
xorg-xwayland)
makedepends=(
git
cmake
ninja
gcc
gdb
meson
vulkan-headers
wayland-protocols
xorgproto)
source=("${_pkgname}::git+https://github.com/vaxerski/Hyprland.git") source=("${_pkgname}::git+https://github.com/vaxerski/Hyprland.git")
conflicts=("${_pkgname}-git" "${_pkgname}" "${_pkgname}-bin")
sha256sums=('SKIP') sha256sums=('SKIP')
options=(!makeflags !buildflags) options=(!makeflags !buildflags)
@@ -24,6 +62,7 @@ pkgver() {
build() { build() {
cd "${srcdir}/${_pkgname}" cd "${srcdir}/${_pkgname}"
git submodule update --init
make all make all
} }

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

56
docs/ISSUE_GUIDELINES.md Normal file
View File

@@ -0,0 +1,56 @@
# Issue Guidelines
First of all, please remember to:
- Check that your issue is not a duplicate
- Read the [FAQ](https://github.com/vaxerski/Hyprland/wiki/FAQ)
- Read the [Configuring Page](https://github.com/vaxerski/Hyprland/wiki/Configuring-Hyprland)
<br/>
# Reporting suggestions
Suggestions are welcome.
Many features can be implemented using bash scripts and Hyprland sockets, read up on those [Here](https://github.com/vaxerski/Hyprland/wiki/IPC). Please do not suggest features that can be implemented as such.
<br/>
# Reporting bugs
All bug reports should have the following:
- Steps to reproduce
- Expected outcome
- Noted outcome
If your bug is one that doesn't crash Hyprland, but feels like invalid behavior, that's all you need to say.
If your bug crashes Hyprland, append additionally:
- The Hyprland log
- Coredump / Coredump analysis (with a stacktrace)
## Obtaining the Hyprland log
If you are in a TTY, and the hyprland session that crashed was the last one you launched, the log will be printed with
```
cat /tmp/hypr/$(ls -t /tmp/hypr/ | head -n 1)/hyprland.log
```
feel free to send it to a file, save, copy, etc.
if you are in a Hyprland session, and you want the log of the last session, use
```
cat /tmp/hypr/$(ls -t /tmp/hypr/ | head -n 2 | tail -n 1)/hyprland.log
```
basically, directories in /tmp/hypr are your sessions.
## Obtaining the Hyprland coredump
If you are on systemd, you can simply use
```
coredumpctl
```
then go to the end (press END on your keyboard) and remember the PID of the last `Hyprland` occurrence. It's the first number after the time, for example `2891`.
exit coredumpctl (ctrl+c) and use
```
coredumpctl info [PID]
```
where `[PID]` is the PID you remembered.

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

View File

@@ -27,7 +27,7 @@ general {
col.active_border=0x66ee1111 col.active_border=0x66ee1111
col.inactive_border=0x66333333 col.inactive_border=0x66333333
damage_tracking=full # experimental, monitor is 100% fine, but full might have some minor bugs, especially with high blur settings! damage_tracking=full # leave it on full unless you hate your GPU and want to make it suffer
} }
decoration { decoration {
@@ -64,7 +64,7 @@ dwindle {
# example binds # example binds
bind=SUPER,Q,exec,kitty bind=SUPER,Q,exec,kitty
bind=SUPER,C,killactive, bind=SUPER,C,killactive,
bind=SUPER,M,exec,pkill Hyprland bind=SUPER,M,exit,
bind=SUPER,E,exec,dolphin bind=SUPER,E,exec,dolphin
bind=SUPER,V,togglefloating, bind=SUPER,V,togglefloating,
bind=SUPER,R,exec,wofi --show drun -o DP-3 bind=SUPER,R,exec,wofi --show drun -o DP-3

12
flake.lock generated
View File

@@ -2,11 +2,11 @@
"nodes": { "nodes": {
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1653407748, "lastModified": 1653931853,
"narHash": "sha256-g9puJaILRTb9ttlLQ7IehpV7Wcy0n+vs8LOFu6ylQcM=", "narHash": "sha256-O3wncIouj9x7gBPntzHeK/Hkmm9M1SGlYq7JI7saTAE=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "5ce6597eca7d7b518c03ecda57d45f9404b5e060", "rev": "f1c167688a6f81f4a51ab542e5f476c8c595e457",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -26,11 +26,11 @@
"flake": false, "flake": false,
"locked": { "locked": {
"host": "gitlab.freedesktop.org", "host": "gitlab.freedesktop.org",
"lastModified": 1653502661, "lastModified": 1653658290,
"narHash": "sha256-unQ1j3jleghIMi340dJTJZZ1ffwm1cI7gaQbdKd7laE=", "narHash": "sha256-zZaona39DOZNL93A1KG3zAi8vDttJBirxacq24hWCn4=",
"owner": "wlroots", "owner": "wlroots",
"repo": "wlroots", "repo": "wlroots",
"rev": "1cb6b2cf673a5b580d7ad79ce2b37c14b14b0268", "rev": "75d31509db8c28e8379fe9570118ef8c82284581",
"type": "gitlab" "type": "gitlab"
}, },
"original": { "original": {

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

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();
@@ -67,7 +72,7 @@ CCompositor::CCompositor() {
m_sWLRScene = wlr_scene_create(); m_sWLRScene = wlr_scene_create();
wlr_scene_attach_output_layout(m_sWLRScene, m_sWLROutputLayout); wlr_scene_attach_output_layout(m_sWLRScene, m_sWLROutputLayout);
m_sWLRXDGShell = wlr_xdg_shell_create(m_sWLDisplay, 2); m_sWLRXDGShell = wlr_xdg_shell_create(m_sWLDisplay, 3);
m_sWLRCursor = wlr_cursor_create(); m_sWLRCursor = wlr_cursor_create();
wlr_cursor_attach_output_layout(m_sWLRCursor, m_sWLROutputLayout); wlr_cursor_attach_output_layout(m_sWLRCursor, m_sWLROutputLayout);
@@ -102,6 +107,8 @@ CCompositor::CCompositor() {
m_sWLRVKeyboardMgr = wlr_virtual_keyboard_manager_v1_create(m_sWLDisplay); m_sWLRVKeyboardMgr = wlr_virtual_keyboard_manager_v1_create(m_sWLDisplay);
m_sWLRVirtPtrMgr = wlr_virtual_pointer_manager_v1_create(m_sWLDisplay); m_sWLRVirtPtrMgr = wlr_virtual_pointer_manager_v1_create(m_sWLDisplay);
m_sWLRToplevelMgr = wlr_foreign_toplevel_manager_v1_create(m_sWLDisplay);
} }
CCompositor::~CCompositor() { CCompositor::~CCompositor() {
@@ -135,6 +142,7 @@ void CCompositor::initAllSignals() {
addWLSignal(&m_sWLRPointerConstraints->events.new_constraint, &Events::listen_newConstraint, m_sWLRPointerConstraints, "PointerConstraints"); addWLSignal(&m_sWLRPointerConstraints->events.new_constraint, &Events::listen_newConstraint, m_sWLRPointerConstraints, "PointerConstraints");
addWLSignal(&m_sWLRXDGDecoMgr->events.new_toplevel_decoration, &Events::listen_NewXDGDeco, m_sWLRXDGDecoMgr, "XDGDecoMgr"); addWLSignal(&m_sWLRXDGDecoMgr->events.new_toplevel_decoration, &Events::listen_NewXDGDeco, m_sWLRXDGDecoMgr, "XDGDecoMgr");
addWLSignal(&m_sWLRVirtPtrMgr->events.new_virtual_pointer, &Events::listen_newVirtPtr, m_sWLRVirtPtrMgr, "VirtPtrMgr"); addWLSignal(&m_sWLRVirtPtrMgr->events.new_virtual_pointer, &Events::listen_newVirtPtr, m_sWLRVirtPtrMgr, "VirtPtrMgr");
addWLSignal(&m_sWLRRenderer->events.destroy, &Events::listen_RendererDestroy, m_sWLRRenderer, "WLRRenderer");
signal(SIGINT, handleCritSignal); signal(SIGINT, handleCritSignal);
signal(SIGTERM, handleCritSignal); signal(SIGTERM, handleCritSignal);
@@ -144,6 +152,12 @@ void CCompositor::cleanupExit() {
if (!m_sWLDisplay) if (!m_sWLDisplay)
return; return;
m_pLastFocus = nullptr;
m_pLastWindow = nullptr;
m_lWorkspaces.clear();
m_lWindows.clear();
if (g_pXWaylandManager->m_sWLRXWayland) { if (g_pXWaylandManager->m_sWLRXWayland) {
wlr_xwayland_destroy(g_pXWaylandManager->m_sWLRXWayland); wlr_xwayland_destroy(g_pXWaylandManager->m_sWLRXWayland);
g_pXWaylandManager->m_sWLRXWayland = nullptr; g_pXWaylandManager->m_sWLRXWayland = nullptr;
@@ -192,6 +206,9 @@ void CCompositor::startCompositor() {
Debug::log(LOG, "Creating the EventManager!"); Debug::log(LOG, "Creating the EventManager!");
g_pEventManager = std::make_unique<CEventManager>(); g_pEventManager = std::make_unique<CEventManager>();
g_pEventManager->startThread(); g_pEventManager->startThread();
Debug::log(LOG, "Creating the HyprDebugOverlay!");
g_pDebugOverlay = std::make_unique<CHyprDebugOverlay>();
// //
// //
@@ -244,6 +261,16 @@ SMonitor* CCompositor::getMonitorFromID(const int& id) {
return nullptr; return nullptr;
} }
SMonitor* CCompositor::getMonitorFromName(const std::string& name) {
for (auto& m : m_lMonitors) {
if (m.szName == name) {
return &m;
}
}
return nullptr;
}
SMonitor* CCompositor::getMonitorFromCursor() { SMonitor* CCompositor::getMonitorFromCursor() {
const auto COORDS = Vector2D(m_sWLRCursor->x, m_sWLRCursor->y); const auto COORDS = Vector2D(m_sWLRCursor->x, m_sWLRCursor->y);
@@ -293,6 +320,15 @@ bool CCompositor::windowExists(CWindow* pWindow) {
CWindow* CCompositor::vectorToWindow(const Vector2D& pos) { CWindow* CCompositor::vectorToWindow(const Vector2D& pos) {
const auto PMONITOR = getMonitorFromVector(pos); const auto PMONITOR = getMonitorFromVector(pos);
if (PMONITOR->specialWorkspaceOpen) {
for (auto& w : m_lWindows) {
wlr_box box = {w.m_vRealPosition.vec().x, w.m_vRealPosition.vec().y, w.m_vRealSize.vec().x, w.m_vRealSize.vec().y};
if (w.m_iWorkspaceID == SPECIAL_WORKSPACE_ID && wlr_box_contains_point(&box, pos.x, pos.y) && w.m_bIsMapped && !w.m_bIsFloating && !w.m_bHidden)
return &w;
}
}
// first loop over floating cuz they're above, m_lWindows should be sorted bottom->top, for tiled it doesn't matter. // first loop over floating cuz they're above, m_lWindows should be sorted bottom->top, for tiled it doesn't matter.
for (auto w = m_lWindows.rbegin(); w != m_lWindows.rend(); w++) { for (auto w = m_lWindows.rbegin(); w != m_lWindows.rend(); w++) {
wlr_box box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y}; wlr_box box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y};
@@ -311,6 +347,15 @@ CWindow* CCompositor::vectorToWindow(const Vector2D& pos) {
CWindow* CCompositor::vectorToWindowTiled(const Vector2D& pos) { CWindow* CCompositor::vectorToWindowTiled(const Vector2D& pos) {
const auto PMONITOR = getMonitorFromVector(pos); const auto PMONITOR = getMonitorFromVector(pos);
if (PMONITOR->specialWorkspaceOpen) {
for (auto& w : m_lWindows) {
wlr_box box = {w.m_vPosition.x, w.m_vPosition.y, w.m_vSize.x, w.m_vSize.y};
if (w.m_iWorkspaceID == SPECIAL_WORKSPACE_ID && wlr_box_contains_point(&box, pos.x, pos.y) && !w.m_bIsFloating && !w.m_bHidden)
return &w;
}
}
for (auto& w : m_lWindows) { for (auto& w : m_lWindows) {
wlr_box box = {w.m_vPosition.x, w.m_vPosition.y, w.m_vSize.x, w.m_vSize.y}; wlr_box box = {w.m_vPosition.x, w.m_vPosition.y, w.m_vSize.x, w.m_vSize.y};
if (w.m_bIsMapped && wlr_box_contains_point(&box, pos.x, pos.y) && w.m_iWorkspaceID == PMONITOR->activeWorkspace && !w.m_bIsFloating && !w.m_bHidden) if (w.m_bIsMapped && wlr_box_contains_point(&box, pos.x, pos.y) && w.m_iWorkspaceID == PMONITOR->activeWorkspace && !w.m_bIsFloating && !w.m_bHidden)
@@ -322,6 +367,16 @@ CWindow* CCompositor::vectorToWindowTiled(const Vector2D& pos) {
CWindow* CCompositor::vectorToWindowIdeal(const Vector2D& pos) { CWindow* CCompositor::vectorToWindowIdeal(const Vector2D& pos) {
const auto PMONITOR = getMonitorFromVector(pos); const auto PMONITOR = getMonitorFromVector(pos);
// special workspace
if (PMONITOR->specialWorkspaceOpen) {
for (auto& w : m_lWindows) {
wlr_box box = {w.m_vPosition.x, w.m_vPosition.y, w.m_vSize.x, w.m_vSize.y};
if (w.m_iWorkspaceID == SPECIAL_WORKSPACE_ID && w.m_bIsMapped && wlr_box_contains_point(&box, pos.x, pos.y) && !w.m_bHidden)
return &w;
}
}
// first loop over floating cuz they're above, m_lWindows should be sorted bottom->top, for tiled it doesn't matter. // first loop over floating cuz they're above, m_lWindows should be sorted bottom->top, for tiled it doesn't matter.
for (auto w = m_lWindows.rbegin(); w != m_lWindows.rend(); w++) { for (auto w = m_lWindows.rbegin(); w != m_lWindows.rend(); w++) {
wlr_box box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y}; wlr_box box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y};
@@ -341,6 +396,14 @@ CWindow* CCompositor::vectorToWindowIdeal(const Vector2D& pos) {
CWindow* CCompositor::windowFromCursor() { CWindow* CCompositor::windowFromCursor() {
const auto PMONITOR = getMonitorFromCursor(); const auto PMONITOR = getMonitorFromCursor();
if (PMONITOR->specialWorkspaceOpen) {
for (auto& w : m_lWindows) {
wlr_box box = {w.m_vPosition.x, w.m_vPosition.y, w.m_vSize.x, w.m_vSize.y};
if (w.m_iWorkspaceID == SPECIAL_WORKSPACE_ID && wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y) && w.m_bIsMapped)
return &w;
}
}
// first loop over floating cuz they're above, m_lWindows should be sorted bottom->top, for tiled it doesn't matter. // first loop over floating cuz they're above, m_lWindows should be sorted bottom->top, for tiled it doesn't matter.
for (auto w = m_lWindows.rbegin(); w != m_lWindows.rend(); w++) { for (auto w = m_lWindows.rbegin(); w != m_lWindows.rend(); w++) {
wlr_box box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y}; wlr_box box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y};
@@ -433,6 +496,9 @@ void CCompositor::focusWindow(CWindow* pWindow, wlr_surface* pSurface) {
wlr_seat_keyboard_notify_clear_focus(m_sSeat.seat); wlr_seat_keyboard_notify_clear_focus(m_sSeat.seat);
wlr_seat_pointer_clear_focus(m_sSeat.seat); wlr_seat_pointer_clear_focus(m_sSeat.seat);
} }
if (PLASTWINDOW->m_phForeignToplevel)
wlr_foreign_toplevel_handle_v1_set_activated(PLASTWINDOW->m_phForeignToplevel, false);
} }
m_pLastWindow = PLASTWINDOW; m_pLastWindow = PLASTWINDOW;
@@ -451,6 +517,9 @@ void CCompositor::focusWindow(CWindow* pWindow, wlr_surface* pSurface) {
// Send an event // Send an event
g_pEventManager->postEvent(SHyprIPCEvent("activewindow", g_pXWaylandManager->getAppIDClass(pWindow) + "," + pWindow->m_szTitle)); g_pEventManager->postEvent(SHyprIPCEvent("activewindow", g_pXWaylandManager->getAppIDClass(pWindow) + "," + pWindow->m_szTitle));
if (pWindow->m_phForeignToplevel)
wlr_foreign_toplevel_handle_v1_set_activated(pWindow->m_phForeignToplevel, true);
} }
void CCompositor::focusSurface(wlr_surface* pSurface, CWindow* pWindowOwner) { void CCompositor::focusSurface(wlr_surface* pSurface, CWindow* pWindowOwner) {
@@ -549,6 +618,9 @@ bool CCompositor::isWorkspaceVisible(const int& w) {
for (auto& m : m_lMonitors) { for (auto& m : m_lMonitors) {
if (m.activeWorkspace == w) if (m.activeWorkspace == w)
return true; return true;
if (m.specialWorkspaceOpen && w == SPECIAL_WORKSPACE_ID)
return true;
} }
return false; return false;
@@ -565,7 +637,15 @@ CWorkspace* CCompositor::getWorkspaceByID(const int& id) {
void CCompositor::sanityCheckWorkspaces() { void CCompositor::sanityCheckWorkspaces() {
for (auto it = m_lWorkspaces.begin(); it != m_lWorkspaces.end(); ++it) { for (auto it = m_lWorkspaces.begin(); it != m_lWorkspaces.end(); ++it) {
if (getWindowsOnWorkspace(it->m_iID) == 0 && !isWorkspaceVisible(it->m_iID)) { if ((getWindowsOnWorkspace(it->m_iID) == 0 && !isWorkspaceVisible(it->m_iID))) {
it = m_lWorkspaces.erase(it);
}
if (it->m_iID == SPECIAL_WORKSPACE_ID && getWindowsOnWorkspace(it->m_iID) == 0) {
for (auto& m : m_lMonitors) {
m.specialWorkspaceOpen = false;
}
it = m_lWorkspaces.erase(it); it = m_lWorkspaces.erase(it);
} }
} }
@@ -595,6 +675,9 @@ void CCompositor::fixXWaylandWindowsOnWorkspace(const int& id) {
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(id); const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(id);
if (!PWORKSPACE)
return;
for (auto& w : m_lWindows) { for (auto& w : m_lWindows) {
if (w.m_iWorkspaceID == id) { if (w.m_iWorkspaceID == id) {
@@ -614,6 +697,9 @@ bool CCompositor::doesSeatAcceptInput(wlr_surface* surface) {
} }
bool CCompositor::isWindowActive(CWindow* pWindow) { bool CCompositor::isWindowActive(CWindow* pWindow) {
if (!m_pLastWindow && !m_pLastFocus)
return false;
if (!windowValidMapped(pWindow)) if (!windowValidMapped(pWindow))
return false; return false;
@@ -790,8 +876,8 @@ CWorkspace* CCompositor::getWorkspaceByString(const std::string& str) {
} }
try { try {
int id = std::stoi(str); std::string name = "";
return getWorkspaceByID(id); return getWorkspaceByID(getWorkspaceIDFromString(str, name));
} catch (std::exception& e) { } catch (std::exception& e) {
Debug::log(ERR, "Error in getWorkspaceByString, invalid id"); Debug::log(ERR, "Error in getWorkspaceByString, invalid id");
} }
@@ -906,4 +992,102 @@ void CCompositor::updateWindowBorderColor(CWindow* pWindow) {
pWindow->m_cRealBorderColor = RENDERDATA.borderColor; pWindow->m_cRealBorderColor = RENDERDATA.borderColor;
else else
pWindow->m_cRealBorderColor = CColor(pWindow == m_pLastWindow ? *ACTIVECOL : *INACTIVECOL); pWindow->m_cRealBorderColor = CColor(pWindow == m_pLastWindow ? *ACTIVECOL : *INACTIVECOL);
}
void CCompositor::moveWindowToWorkspace(CWindow* pWindow, const std::string& work) {
m_pLastWindow = pWindow;
g_pKeybindManager->moveActiveToWorkspace(work);
g_pInputManager->refocus();
}
int CCompositor::getNextAvailableMonitorID() {
int64_t topID = -1;
for (auto& m : m_lMonitors) {
if ((int64_t)m.ID > topID)
topID = m.ID;
}
return topID + 1;
}
void CCompositor::moveWorkspaceToMonitor(CWorkspace* pWorkspace, SMonitor* pMonitor) {
// We trust the workspace and monitor to be correct.
if (pWorkspace->m_iMonitorID == pMonitor->ID)
return;
Debug::log(LOG, "moveWorkspaceToMonitor: Moving %d to monitor %d", pWorkspace->m_iID, pMonitor->ID);
const auto POLDMON = getMonitorFromID(pWorkspace->m_iMonitorID);
const bool SWITCHINGISACTIVE = POLDMON->activeWorkspace == pWorkspace->m_iID;
// fix old mon
int nextWorkspaceOnMonitorID = -1;
for (auto& w : m_lWorkspaces) {
if (w.m_iMonitorID == POLDMON->ID && w.m_iID != pWorkspace->m_iID) {
nextWorkspaceOnMonitorID = w.m_iID;
break;
}
}
if (nextWorkspaceOnMonitorID == -1) {
nextWorkspaceOnMonitorID = 1;
while (getWorkspaceByID(nextWorkspaceOnMonitorID))
nextWorkspaceOnMonitorID++;
Debug::log(LOG, "moveWorkspaceToMonitor: Plugging gap with new %d", nextWorkspaceOnMonitorID);
}
Debug::log(LOG, "moveWorkspaceToMonitor: Plugging gap with existing %d", nextWorkspaceOnMonitorID);
g_pKeybindManager->focusMonitor(std::to_string(POLDMON->ID));
g_pKeybindManager->changeworkspace(std::to_string(nextWorkspaceOnMonitorID));
// move the workspace
pWorkspace->m_iMonitorID = pMonitor->ID;
pWorkspace->moveToMonitor(pMonitor->ID);
for (auto& w : m_lWindows) {
if (w.m_iWorkspaceID == pWorkspace->m_iID)
w.m_iMonitorID = pMonitor->ID;
}
if (SWITCHINGISACTIVE) { // if it was active, preserve its' status. If it wasn't, don't.
Debug::log(LOG, "moveWorkspaceToMonitor: SWITCHINGISACTIVE, active %d -> %d", pMonitor->activeWorkspace, pWorkspace->m_iID);
if (const auto PWORKSPACE = getWorkspaceByID(pMonitor->activeWorkspace); PWORKSPACE)
getWorkspaceByID(pMonitor->activeWorkspace)->startAnim(false, false);
pMonitor->activeWorkspace = pWorkspace->m_iID;
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(pMonitor->ID);
pWorkspace->startAnim(true, true, true);
wlr_cursor_warp(m_sWLRCursor, m_sSeat.mouse->mouse, pMonitor->vecPosition.x + pMonitor->vecTransformedSize.x / 2, pMonitor->vecPosition.y + pMonitor->vecTransformedSize.y / 2);
}
// finalize
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(POLDMON->ID);
g_pInputManager->refocus();
}
bool CCompositor::workspaceIDOutOfBounds(const int& id) {
int lowestID = 99999;
int highestID = -99999;
for (auto& w : m_lWorkspaces) {
if (w.m_iID < lowestID)
lowestID = w.m_iID;
if (w.m_iID > highestID)
highestID = w.m_iID;
}
return std::clamp(id, lowestID, highestID) != id;
} }

View File

@@ -15,6 +15,7 @@
#include "managers/KeybindManager.hpp" #include "managers/KeybindManager.hpp"
#include "managers/AnimationManager.hpp" #include "managers/AnimationManager.hpp"
#include "managers/EventManager.hpp" #include "managers/EventManager.hpp"
#include "debug/HyprDebugOverlay.hpp"
#include "helpers/Monitor.hpp" #include "helpers/Monitor.hpp"
#include "helpers/Workspace.hpp" #include "helpers/Workspace.hpp"
#include "Window.hpp" #include "Window.hpp"
@@ -57,10 +58,12 @@ public:
wlr_server_decoration_manager* m_sWLRServerDecoMgr; wlr_server_decoration_manager* m_sWLRServerDecoMgr;
wlr_xdg_decoration_manager_v1* m_sWLRXDGDecoMgr; wlr_xdg_decoration_manager_v1* m_sWLRXDGDecoMgr;
wlr_virtual_pointer_manager_v1* m_sWLRVirtPtrMgr; wlr_virtual_pointer_manager_v1* m_sWLRVirtPtrMgr;
wlr_foreign_toplevel_manager_v1* m_sWLRToplevelMgr;
// ------------------------------------------------- // // ------------------------------------------------- //
const char* m_szWLDisplaySocket; const char* m_szWLDisplaySocket;
std::string m_szInstanceSignature = "";
std::list<SMonitor> m_lMonitors; std::list<SMonitor> m_lMonitors;
std::list<CWindow> m_lWindows; std::list<CWindow> m_lWindows;
@@ -84,6 +87,7 @@ public:
// ------------------------------------------------- // // ------------------------------------------------- //
SMonitor* getMonitorFromID(const int&); SMonitor* getMonitorFromID(const int&);
SMonitor* getMonitorFromName(const std::string&);
SMonitor* getMonitorFromCursor(); SMonitor* getMonitorFromCursor();
SMonitor* getMonitorFromVector(const Vector2D&); SMonitor* getMonitorFromVector(const Vector2D&);
void removeWindowFromVectorSafe(CWindow*); void removeWindowFromVectorSafe(CWindow*);
@@ -123,6 +127,10 @@ public:
SMonitor* getMonitorInDirection(const char&); SMonitor* getMonitorInDirection(const char&);
void updateAllWindowsBorders(); void updateAllWindowsBorders();
void updateWindowBorderColor(CWindow*); void updateWindowBorderColor(CWindow*);
void moveWindowToWorkspace(CWindow*, const std::string&);
int getNextAvailableMonitorID();
void moveWorkspaceToMonitor(CWorkspace*, SMonitor*);
bool workspaceIDOutOfBounds(const int&);
private: private:
void initAllSignals(); void initAllSignals();

View File

@@ -13,4 +13,34 @@ CWindow::~CWindow() {
g_pCompositor->m_pLastFocus = nullptr; g_pCompositor->m_pLastFocus = nullptr;
g_pCompositor->m_pLastWindow = nullptr; g_pCompositor->m_pLastWindow = nullptr;
} }
}
wlr_box CWindow::getFullWindowBoundingBox() {
SWindowDecorationExtents maxExtents;
for (auto& wd : m_dWindowDecorations) {
const auto EXTENTS = wd->getWindowDecorationExtents();
if (EXTENTS.topLeft.x > maxExtents.topLeft.x)
maxExtents.topLeft.x = EXTENTS.topLeft.x;
if (EXTENTS.topLeft.y > maxExtents.topLeft.y)
maxExtents.topLeft.y = EXTENTS.topLeft.y;
if (EXTENTS.bottomRight.x > maxExtents.bottomRight.x)
maxExtents.bottomRight.x = EXTENTS.bottomRight.x;
if (EXTENTS.bottomRight.y > maxExtents.bottomRight.y)
maxExtents.bottomRight.y = EXTENTS.bottomRight.y;
}
// Add extents to the real base BB and return
wlr_box finalBox = {m_vRealPosition.vec().x - maxExtents.topLeft.x,
m_vRealPosition.vec().y - maxExtents.topLeft.y,
m_vRealSize.vec().x + maxExtents.topLeft.x + maxExtents.bottomRight.x,
m_vRealSize.vec().y + maxExtents.topLeft.y + maxExtents.bottomRight.y};
return finalBox;
} }

View File

@@ -4,13 +4,17 @@
#include "events/Events.hpp" #include "events/Events.hpp"
#include "helpers/SubsurfaceTree.hpp" #include "helpers/SubsurfaceTree.hpp"
#include "helpers/AnimatedVariable.hpp" #include "helpers/AnimatedVariable.hpp"
#include "render/decorations/IHyprWindowDecoration.hpp"
#include <deque>
struct SWindowSpecialRenderData { struct SWindowSpecialRenderData {
float alpha = 1.f; float alpha = 1.f;
float alphaInactive = -1.f; // -1 means unset
}; };
struct SWindowAdditionalConfigData { struct SWindowAdditionalConfigData {
std::string animationStyle = ""; std::string animationStyle = "";
int rounding = -1; // -1 means no
}; };
class CWindow { class CWindow {
@@ -81,10 +85,18 @@ public:
CAnimatedVariable m_fAlpha; CAnimatedVariable m_fAlpha;
bool m_bFadingOut = false; bool m_bFadingOut = false;
bool m_bReadyToDelete = false; bool m_bReadyToDelete = false;
Vector2D m_vOriginalClosedPos; // these will be used for calculations later on in
Vector2D m_vOriginalClosedSize; // drawing the closing animations
// For hidden windows and stuff // For hidden windows and stuff
bool m_bHidden = false; bool m_bHidden = false;
// Foreign Toplevel proto
wlr_foreign_toplevel_handle_v1* m_phForeignToplevel = nullptr;
// Window decorations
std::deque<std::unique_ptr<IHyprWindowDecoration>> m_dWindowDecorations;
// Special render data, rules, etc // Special render data, rules, etc
SWindowSpecialRenderData m_sSpecialRenderData; SWindowSpecialRenderData m_sSpecialRenderData;
SWindowAdditionalConfigData m_sAdditionalConfigData; SWindowAdditionalConfigData m_sAdditionalConfigData;
@@ -94,4 +106,7 @@ public:
return m_uSurface.xdg == rhs.m_uSurface.xdg && m_uSurface.xwayland == rhs.m_uSurface.xwayland && m_vPosition == rhs.m_vPosition && m_vSize == rhs.m_vSize && m_bFadingOut == rhs.m_bFadingOut; return m_uSurface.xdg == rhs.m_uSurface.xdg && m_uSurface.xwayland == rhs.m_uSurface.xwayland && m_vPosition == rhs.m_vPosition && m_vSize == rhs.m_vSize && m_bFadingOut == rhs.m_bFadingOut;
} }
// methods
wlr_box getFullWindowBoundingBox();
}; };

View File

@@ -35,20 +35,24 @@ void CConfigManager::setDefaultVars() {
configValues["debug:int"].intValue = 0; configValues["debug:int"].intValue = 0;
configValues["debug:log_damage"].intValue = 0; configValues["debug:log_damage"].intValue = 0;
configValues["debug:overlay"].intValue = 0;
configValues["decoration:rounding"].intValue = 1; configValues["decoration:rounding"].intValue = 1;
configValues["decoration:blur"].intValue = 1; configValues["decoration:blur"].intValue = 1;
configValues["decoration:blur_size"].intValue = 8; configValues["decoration:blur_size"].intValue = 8;
configValues["decoration:blur_passes"].intValue = 1; configValues["decoration:blur_passes"].intValue = 1;
configValues["decoration:blur_ignore_opacity"].intValue = 0;
configValues["decoration:active_opacity"].floatValue = 1; configValues["decoration:active_opacity"].floatValue = 1;
configValues["decoration:inactive_opacity"].floatValue = 1; configValues["decoration:inactive_opacity"].floatValue = 1;
configValues["decoration:fullscreen_opacity"].floatValue = 1; configValues["decoration:fullscreen_opacity"].floatValue = 1;
configValues["decoration:multisample_edges"].intValue = 0;
configValues["dwindle:pseudotile"].intValue = 0; configValues["dwindle:pseudotile"].intValue = 0;
configValues["dwindle:col.group_border"].intValue = 0x66777700; configValues["dwindle:col.group_border"].intValue = 0x66777700;
configValues["dwindle:col.group_border_active"].intValue = 0x66ffff00; configValues["dwindle:col.group_border_active"].intValue = 0x66ffff00;
configValues["dwindle:force_split"].intValue = 0; configValues["dwindle:force_split"].intValue = 0;
configValues["dwindle:preserve_split"].intValue = 0; configValues["dwindle:preserve_split"].intValue = 0;
configValues["dwindle:special_scale_factor"].floatValue = 0.8f;
configValues["animations:enabled"].intValue = 1; configValues["animations:enabled"].intValue = 1;
configValues["animations:speed"].floatValue = 7.f; configValues["animations:speed"].floatValue = 7.f;
@@ -78,6 +82,8 @@ void CConfigManager::setDefaultVars() {
configValues["input:repeat_rate"].intValue = 25; configValues["input:repeat_rate"].intValue = 25;
configValues["input:repeat_delay"].intValue = 600; configValues["input:repeat_delay"].intValue = 600;
configValues["input:natural_scroll"].intValue = 0; configValues["input:natural_scroll"].intValue = 0;
configValues["input:numlock_by_default"].intValue = 0;
configValues["input:force_no_accel"].intValue = 0;
configValues["input:touchpad:disable_while_typing"].intValue = 1; configValues["input:touchpad:disable_while_typing"].intValue = 1;
configValues["input:follow_mouse"].intValue = 1; configValues["input:follow_mouse"].intValue = 1;
@@ -184,10 +190,24 @@ void CConfigManager::handleMonitor(const std::string& command, const std::string
nextItem(); nextItem();
if (curitem == "disable" || curitem == "disabled" || curitem == "addreserved") { if (curitem == "disable" || curitem == "disabled" || curitem == "addreserved" || curitem == "transform") {
if (curitem == "disable" || curitem == "disabled") if (curitem == "disable" || curitem == "disabled")
newrule.disabled = true; newrule.disabled = true;
else if (curitem == "addreserved") { else if (curitem == "transform") {
nextItem();
wl_output_transform transform = (wl_output_transform)std::stoi(curitem);
// overwrite if exists
for (auto& r : m_dMonitorRules) {
if (r.name == newrule.name) {
r.transform = transform;
return;
}
}
return;
} else if (curitem == "addreserved") {
nextItem(); nextItem();
int top = std::stoi(curitem); int top = std::stoi(curitem);
@@ -411,6 +431,7 @@ void CConfigManager::handleWindowRule(const std::string& command, const std::str
&& RULE.find("monitor") != 0 && RULE.find("monitor") != 0
&& RULE.find("nofocus") != 0 && RULE.find("nofocus") != 0
&& RULE.find("animation") != 0 && RULE.find("animation") != 0
&& RULE.find("rounding") != 0
&& RULE.find("workspace") != 0) { && RULE.find("workspace") != 0) {
Debug::log(ERR, "Invalid rule found: %s", RULE.c_str()); Debug::log(ERR, "Invalid rule found: %s", RULE.c_str());
parseError = "Invalid rule found: " + RULE; parseError = "Invalid rule found: " + RULE;

View File

@@ -30,6 +30,7 @@ struct SMonitorRule {
float refreshRate = 60; float refreshRate = 60;
int defaultWorkspaceID = -1; int defaultWorkspaceID = -1;
bool disabled = false; bool disabled = false;
wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL;
}; };
struct SMonitorAdditionalReservedArea { struct SMonitorAdditionalReservedArea {

View File

@@ -34,7 +34,7 @@ general {
col.active_border=0x66ee1111 col.active_border=0x66ee1111
col.inactive_border=0x66333333 col.inactive_border=0x66333333
damage_tracking=full # experimental, monitor is 100% fine, but full might have some minor bugs, especially with high blur settings! damage_tracking=full # leave it on full unless you hate your GPU and want to make it suffer
} }
decoration { decoration {
@@ -71,7 +71,7 @@ dwindle {
# example binds # example binds
bind=SUPER,Q,exec,kitty bind=SUPER,Q,exec,kitty
bind=SUPER,C,killactive, bind=SUPER,C,killactive,
bind=SUPER,M,exec,pkill Hyprland bind=SUPER,M,exit,
bind=SUPER,E,exec,dolphin bind=SUPER,E,exec,dolphin
bind=SUPER,V,togglefloating, bind=SUPER,V,togglefloating,
bind=SUPER,R,exec,wofi --show drun -o DP-3 bind=SUPER,R,exec,wofi --show drun -o DP-3

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\n", if (w.m_bIsMapped)
&w, w.m_szTitle.c_str(), (int)w.m_vRealPosition.vec().x, (int)w.m_vRealPosition.vec().y, (int)w.m_vRealSize.vec().x, (int)w.m_vRealSize.vec().y, w.m_iWorkspaceID, (w.m_iWorkspaceID == -1 ? "" : g_pCompositor->getWorkspaceByID(w.m_iWorkspaceID)->m_szName.c_str()), (int)w.m_bIsFloating); result += getFormat("Window %x -> %s:\n\tat: %i,%i\n\tsize: %i,%i\n\tworkspace: %i (%s)\n\tfloating: %i\n\tmonitor: %i\n\tclass: %s\n\n",
&w, w.m_szTitle.c_str(), (int)w.m_vRealPosition.vec().x, (int)w.m_vRealPosition.vec().y, (int)w.m_vRealSize.vec().x, (int)w.m_vRealSize.vec().y, w.m_iWorkspaceID, (w.m_iWorkspaceID == -1 ? "" : g_pCompositor->getWorkspaceByID(w.m_iWorkspaceID) ? g_pCompositor->getWorkspaceByID(w.m_iWorkspaceID)->m_szName.c_str() : std::string("Invalid workspace " + std::to_string(w.m_iWorkspaceID)).c_str()), (int)w.m_bIsFloating, w.m_iMonitorID, g_pXWaylandManager->getAppIDClass(&w).c_str());
} }
return result; return result;
} }
@@ -47,8 +48,8 @@ std::string activeWindowRequest() {
if (!g_pCompositor->windowValidMapped(PWINDOW)) if (!g_pCompositor->windowValidMapped(PWINDOW))
return "Invalid"; return "Invalid";
return getFormat("Window %x -> %s:\n\tat: %i,%i\n\tsize: %i, %i\n\tworkspace: %i (%s)\n\tfloating: %i\n\n", return getFormat("Window %x -> %s:\n\tat: %i,%i\n\tsize: %i,%i\n\tworkspace: %i (%s)\n\tfloating: %i\n\tmonitor: %i\n\tclass: %s\n\n",
PWINDOW, PWINDOW->m_szTitle.c_str(), (int)PWINDOW->m_vRealPosition.vec().x, (int)PWINDOW->m_vRealPosition.vec().y, (int)PWINDOW->m_vRealSize.vec().x, (int)PWINDOW->m_vRealSize.vec().y, PWINDOW->m_iWorkspaceID, (PWINDOW->m_iWorkspaceID == -1 ? "" : g_pCompositor->getWorkspaceByID(PWINDOW->m_iWorkspaceID)->m_szName.c_str()), (int)PWINDOW->m_bIsFloating); PWINDOW, PWINDOW->m_szTitle.c_str(), (int)PWINDOW->m_vRealPosition.vec().x, (int)PWINDOW->m_vRealPosition.vec().y, (int)PWINDOW->m_vRealSize.vec().x, (int)PWINDOW->m_vRealSize.vec().y, PWINDOW->m_iWorkspaceID, (PWINDOW->m_iWorkspaceID == -1 ? "" : g_pCompositor->getWorkspaceByID(PWINDOW->m_iWorkspaceID)->m_szName.c_str()), (int)PWINDOW->m_bIsFloating, (int)PWINDOW->m_iMonitorID, g_pXWaylandManager->getAppIDClass(PWINDOW).c_str());
} }
std::string layersRequest() { std::string layersRequest() {
@@ -72,6 +73,24 @@ std::string layersRequest() {
return result; return result;
} }
std::string devicesRequest() {
std::string result = "";
result += "mice:\n";
for (auto& m : g_pInputManager->m_lMice) {
result += getFormat("\tMouse at %x:\n\t\t%s\n", &m, m.mouse->name);
}
result += "\n\nKeyboards:\n";
for (auto& k : g_pInputManager->m_lKeyboards) {
result += getFormat("\tKeyboard at %x:\n\t\t%s\n", &k, k.keyboard->name);
}
return result;
}
std::string versionRequest() { std::string versionRequest() {
std::string result = "Hyprland, built from branch " + std::string(GIT_BRANCH) + " at commit " + GIT_COMMIT_HASH + GIT_DIRTY + " (" + GIT_COMMIT_MESSAGE + ").\nflags: (if any)\n"; std::string result = "Hyprland, built from branch " + std::string(GIT_BRANCH) + " at commit " + GIT_COMMIT_HASH + GIT_DIRTY + " (" + GIT_COMMIT_MESSAGE + ").\nflags: (if any)\n";
@@ -186,6 +205,8 @@ std::string getReply(std::string request) {
return versionRequest(); return versionRequest();
else if (request == "reload") else if (request == "reload")
return reloadRequest(); return reloadRequest();
else if (request == "devices")
return devicesRequest();
else if (request.find("dispatch") == 0) else if (request.find("dispatch") == 0)
return dispatchRequest(request); return dispatchRequest(request);
else if (request.find("keyword") == 0) else if (request.find("keyword") == 0)
@@ -246,11 +267,11 @@ void HyprCtl::startHyprCtlSocket() {
return; return;
} }
unlink("/tmp/hypr/.socket.sock");
sockaddr_un SERVERADDRESS = {.sun_family = AF_UNIX}; sockaddr_un SERVERADDRESS = {.sun_family = AF_UNIX};
strcpy(SERVERADDRESS.sun_path, "/tmp/hypr/.socket.sock"); std::string socketPath = "/tmp/hypr/" + g_pCompositor->m_szInstanceSignature + "/.socket.sock";
strcpy(SERVERADDRESS.sun_path, socketPath.c_str());
bind(SOCKET, (sockaddr*)&SERVERADDRESS, SUN_LEN(&SERVERADDRESS)); bind(SOCKET, (sockaddr*)&SERVERADDRESS, SUN_LEN(&SERVERADDRESS));
@@ -262,7 +283,7 @@ void HyprCtl::startHyprCtlSocket() {
char readBuffer[1024] = {0}; char readBuffer[1024] = {0};
Debug::log(LOG, "Hypr socket started."); Debug::log(LOG, "Hypr socket started at %s", socketPath.c_str());
while(1) { while(1) {
const auto ACCEPTEDCONNECTION = accept(SOCKET, (sockaddr*)&clientAddress, &clientSize); const auto ACCEPTEDCONNECTION = accept(SOCKET, (sockaddr*)&clientAddress, &clientSize);

View File

@@ -0,0 +1,181 @@
#include "HyprDebugOverlay.hpp"
#include "../Compositor.hpp"
void CHyprMonitorDebugOverlay::renderData(SMonitor* pMonitor, float µs) {
m_dLastRenderTimes.push_back(µs / 1000.f);
if (m_dLastRenderTimes.size() > (long unsigned int)pMonitor->refreshRate)
m_dLastRenderTimes.pop_front();
if (!m_pMonitor)
m_pMonitor = pMonitor;
}
void CHyprMonitorDebugOverlay::renderDataNoOverlay(SMonitor* pMonitor, float µs) {
m_dLastRenderTimesNoOverlay.push_back(µs / 1000.f);
if (m_dLastRenderTimesNoOverlay.size() > (long unsigned int)pMonitor->refreshRate)
m_dLastRenderTimesNoOverlay.pop_front();
if (!m_pMonitor)
m_pMonitor = pMonitor;
}
void CHyprMonitorDebugOverlay::frameData(SMonitor* pMonitor) {
m_dLastFrametimes.push_back(std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now() - m_tpLastFrame).count() / 1000.f);
if (m_dLastFrametimes.size() > (long unsigned int)pMonitor->refreshRate)
m_dLastFrametimes.pop_front();
m_tpLastFrame = std::chrono::high_resolution_clock::now();
if (!m_pMonitor)
m_pMonitor = pMonitor;
}
int CHyprMonitorDebugOverlay::draw(int offset) {
if (!m_pMonitor)
return 0;
int yOffset = offset;
cairo_text_extents_t cairoExtents;
float maxX = 0;
std::string text = "";
// get avg fps
float avgFrametime = 0;
for (auto& ft : m_dLastFrametimes) {
avgFrametime += ft;
}
avgFrametime /= m_dLastFrametimes.size() == 0 ? 1 : m_dLastFrametimes.size();
float avgRenderTime = 0;
for (auto& rt : m_dLastRenderTimes) {
avgRenderTime += rt;
}
avgRenderTime /= m_dLastRenderTimes.size() == 0 ? 1 : m_dLastRenderTimes.size();
float avgRenderTimeNoOverlay = 0;
for (auto& rt : m_dLastRenderTimesNoOverlay) {
avgRenderTimeNoOverlay += rt;
}
avgRenderTimeNoOverlay /= m_dLastRenderTimes.size() == 0 ? 1 : m_dLastRenderTimes.size();
const float FPS = 1.f / (avgFrametime / 1000.f); // frametimes are in ms
const float idealFPS = m_dLastFrametimes.size();
cairo_select_font_face(g_pDebugOverlay->m_pCairo, "Noto Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
cairo_set_font_size(g_pDebugOverlay->m_pCairo, 10);
cairo_set_source_rgba(g_pDebugOverlay->m_pCairo, 1.f, 1.f, 1.f, 1.f);
yOffset += 10;
cairo_move_to(g_pDebugOverlay->m_pCairo, 0, yOffset);
text = m_pMonitor->szName;
cairo_show_text(g_pDebugOverlay->m_pCairo, text.c_str());
cairo_text_extents(g_pDebugOverlay->m_pCairo, text.c_str(), &cairoExtents);
if (cairoExtents.width > maxX) maxX = cairoExtents.width;
cairo_set_font_size(g_pDebugOverlay->m_pCairo, 16);
if (FPS > idealFPS * 0.95f)
cairo_set_source_rgba(g_pDebugOverlay->m_pCairo, 0.2f, 1.f, 0.2f, 1.f);
else if (FPS > idealFPS * 0.8f)
cairo_set_source_rgba(g_pDebugOverlay->m_pCairo, 1.f, 1.f, 0.2f, 1.f);
else
cairo_set_source_rgba(g_pDebugOverlay->m_pCairo, 1.f, 0.2f, 0.2f, 1.f);
yOffset += 17;
cairo_move_to(g_pDebugOverlay->m_pCairo, 0, yOffset);
text = std::string(std::to_string((int)FPS) + " FPS");
cairo_show_text(g_pDebugOverlay->m_pCairo, text.c_str());
cairo_text_extents(g_pDebugOverlay->m_pCairo, text.c_str(), &cairoExtents);
if (cairoExtents.width > maxX) maxX = cairoExtents.width;
cairo_set_font_size(g_pDebugOverlay->m_pCairo, 10);
cairo_set_source_rgba(g_pDebugOverlay->m_pCairo, 1.f, 1.f, 1.f, 1.f);
yOffset += 11;
cairo_move_to(g_pDebugOverlay->m_pCairo, 0, yOffset);
text = std::string("Avg Frametime: " + std::to_string((int)avgFrametime) + "." + std::to_string((int)(avgFrametime * 10.f) % 10) + "ms");
cairo_show_text(g_pDebugOverlay->m_pCairo, text.c_str());
cairo_text_extents(g_pDebugOverlay->m_pCairo, text.c_str(), &cairoExtents);
if (cairoExtents.width > maxX) maxX = cairoExtents.width;
yOffset += 11;
cairo_move_to(g_pDebugOverlay->m_pCairo, 0, yOffset);
text = std::string("Avg Rendertime: " + std::to_string((int)avgRenderTime) + "." + std::to_string((int)(avgRenderTime * 10.f) % 10) + "ms");
cairo_show_text(g_pDebugOverlay->m_pCairo, text.c_str());
cairo_text_extents(g_pDebugOverlay->m_pCairo, text.c_str(), &cairoExtents);
if (cairoExtents.width > maxX) maxX = cairoExtents.width;
yOffset += 11;
cairo_move_to(g_pDebugOverlay->m_pCairo, 0, yOffset);
text = std::string("Avg Rendertime (no overlay): " + std::to_string((int)avgRenderTimeNoOverlay) + "." + std::to_string((int)(avgRenderTimeNoOverlay * 10.f) % 10) + "ms");
cairo_show_text(g_pDebugOverlay->m_pCairo, text.c_str());
cairo_text_extents(g_pDebugOverlay->m_pCairo, text.c_str(), &cairoExtents);
if (cairoExtents.width > maxX) maxX = cairoExtents.width;
yOffset += 11;
g_pHyprRenderer->damageBox(&m_wbLastDrawnBox);
m_wbLastDrawnBox = {(int)g_pCompositor->m_lMonitors.front().vecPosition.x, (int)g_pCompositor->m_lMonitors.front().vecPosition.y + offset - 1, (int)maxX + 2, yOffset - offset + 2};
g_pHyprRenderer->damageBox(&m_wbLastDrawnBox);
return yOffset - offset;
}
void CHyprDebugOverlay::renderData(SMonitor* pMonitor, float µs) {
m_mMonitorOverlays[pMonitor].renderData(pMonitor, µs);
}
void CHyprDebugOverlay::renderDataNoOverlay(SMonitor* pMonitor, float µs) {
m_mMonitorOverlays[pMonitor].renderDataNoOverlay(pMonitor, µs);
}
void CHyprDebugOverlay::frameData(SMonitor* pMonitor) {
m_mMonitorOverlays[pMonitor].frameData(pMonitor);
}
void CHyprDebugOverlay::draw() {
const auto PMONITOR = &g_pCompositor->m_lMonitors.front();
if (!m_pCairoSurface || !m_pCairo) {
m_pCairoSurface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, PMONITOR->vecSize.x, PMONITOR->vecSize.y);
m_pCairo = cairo_create(m_pCairoSurface);
}
// clear the pixmap
cairo_save(m_pCairo);
cairo_set_operator(m_pCairo, CAIRO_OPERATOR_CLEAR);
cairo_paint(m_pCairo);
cairo_restore(m_pCairo);
// draw the things
int offsetY = 0;
for (auto& m : g_pCompositor->m_lMonitors) {
offsetY += m_mMonitorOverlays[&m].draw(offsetY);
offsetY += 5; // for padding between mons
}
cairo_surface_flush(m_pCairoSurface);
// copy the data to an OpenGL texture we have
const auto DATA = cairo_image_surface_get_data(m_pCairoSurface);
m_tTexture.allocate();
glBindTexture(GL_TEXTURE_2D, m_tTexture.m_iTexID);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
#ifndef GLES2
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_BLUE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED);
#endif
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, PMONITOR->vecSize.x, PMONITOR->vecSize.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, DATA);
wlr_box pMonBox = {0,0,PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y};
g_pHyprOpenGL->renderTexture(m_tTexture, &pMonBox, 255.f);
}

View File

@@ -0,0 +1,47 @@
#pragma once
#include "../defines.hpp"
#include "../helpers/Monitor.hpp"
#include "../render/Texture.hpp"
#include <deque>
#include <cairo/cairo.h>
#include <unordered_map>
class CHyprMonitorDebugOverlay {
public:
int draw(int offset);
void renderData(SMonitor* pMonitor, float µs);
void renderDataNoOverlay(SMonitor* pMonitor, float µs);
void frameData(SMonitor* pMonitor);
private:
std::deque<float> m_dLastFrametimes;
std::deque<float> m_dLastRenderTimes;
std::deque<float> m_dLastRenderTimesNoOverlay;
std::chrono::high_resolution_clock::time_point m_tpLastFrame;
SMonitor* m_pMonitor = nullptr;
wlr_box m_wbLastDrawnBox;
};
class CHyprDebugOverlay {
public:
void draw();
void renderData(SMonitor*, float µs);
void renderDataNoOverlay(SMonitor*, float µs);
void frameData(SMonitor*);
private:
std::unordered_map<SMonitor*, CHyprMonitorDebugOverlay> m_mMonitorOverlays;
cairo_surface_t* m_pCairoSurface = nullptr;
cairo_t* m_pCairo = nullptr;
CTexture m_tTexture;
friend class CHyprMonitorDebugOverlay;
};
inline std::unique_ptr<CHyprDebugOverlay> g_pDebugOverlay;

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

@@ -65,3 +65,5 @@
#ifndef GIT_DIRTY #ifndef GIT_DIRTY
#define GIT_DIRTY "?" #define GIT_DIRTY "?"
#endif #endif
#define SPECIAL_WORKSPACE_ID -99

View File

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

View File

@@ -58,7 +58,12 @@ void Events::listener_destroyLayerSurface(void* owner, void* data) {
Debug::log(LOG, "LayerSurface %x destroyed", layersurface->layerSurface); Debug::log(LOG, "LayerSurface %x destroyed", layersurface->layerSurface);
if (!layersurface->fadingOut) { const auto PMONITOR = g_pCompositor->getMonitorFromID(layersurface->monitorID);
if (!g_pCompositor->getMonitorFromID(layersurface->monitorID))
Debug::log(WARN, "Layersurface destroyed on an invalid monitor (removed?)");
if (!layersurface->fadingOut && PMONITOR) {
Debug::log(LOG, "Removing LayerSurface that wasn't mapped."); Debug::log(LOG, "Removing LayerSurface that wasn't mapped.");
layersurface->alpha.setValueAndWarp(0.f); layersurface->alpha.setValueAndWarp(0.f);
layersurface->fadingOut = true; layersurface->fadingOut = true;
@@ -70,8 +75,6 @@ void Events::listener_destroyLayerSurface(void* owner, void* data) {
layersurface->hyprListener_unmapLayerSurface.removeCallback(); layersurface->hyprListener_unmapLayerSurface.removeCallback();
layersurface->hyprListener_newPopup.removeCallback(); layersurface->hyprListener_newPopup.removeCallback();
const auto PMONITOR = g_pCompositor->getMonitorFromID(layersurface->monitorID);
// rearrange to fix the reserved areas // rearrange to fix the reserved areas
if (PMONITOR) { if (PMONITOR) {
g_pHyprRenderer->arrangeLayersForMonitor(PMONITOR->ID); g_pHyprRenderer->arrangeLayersForMonitor(PMONITOR->ID);
@@ -131,6 +134,11 @@ void Events::listener_unmapLayerSurface(void* owner, void* data) {
Debug::log(LOG, "LayerSurface %x unmapped", layersurface->layerSurface); Debug::log(LOG, "LayerSurface %x unmapped", layersurface->layerSurface);
if (!g_pCompositor->getMonitorFromID(layersurface->monitorID)) {
Debug::log(WARN, "Layersurface unmapping on invalid monitor (removed?) ignoring.");
return;
}
// make a snapshot and start fade // make a snapshot and start fade
g_pHyprOpenGL->makeLayerSnapshot(layersurface); g_pHyprOpenGL->makeLayerSnapshot(layersurface);
layersurface->alpha = 0.f; layersurface->alpha = 0.f;
@@ -152,6 +160,12 @@ void Events::listener_unmapLayerSurface(void* owner, void* data) {
wlr_box geomFixed = {layersurface->geometry.x + PMONITOR->vecPosition.x, layersurface->geometry.y + PMONITOR->vecPosition.y, layersurface->geometry.width, layersurface->geometry.height}; wlr_box geomFixed = {layersurface->geometry.x + PMONITOR->vecPosition.x, layersurface->geometry.y + PMONITOR->vecPosition.y, layersurface->geometry.width, layersurface->geometry.height};
g_pHyprRenderer->damageBox(&geomFixed); g_pHyprRenderer->damageBox(&geomFixed);
geomFixed = {layersurface->geometry.x + (int)PMONITOR->vecPosition.x, layersurface->geometry.y + (int)PMONITOR->vecPosition.y, (int)layersurface->layerSurface->surface->current.width, (int)layersurface->layerSurface->surface->current.height};
g_pHyprRenderer->damageBox(&geomFixed);
geomFixed = {layersurface->geometry.x, layersurface->geometry.y, (int)layersurface->layerSurface->surface->current.width, (int)layersurface->layerSurface->surface->current.height};
layersurface->geometry = geomFixed; // because the surface can overflow... for some reason?
} }
void Events::listener_commitLayerSurface(void* owner, void* data) { void Events::listener_commitLayerSurface(void* owner, void* data) {

View File

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

@@ -48,6 +48,16 @@ void Events::listener_newOutput(wl_listener* listener, void* data) {
// new monitor added, let's accomodate for that. // new monitor added, let's accomodate for that.
const auto OUTPUT = (wlr_output*)data; const auto OUTPUT = (wlr_output*)data;
if (!OUTPUT->name) {
Debug::log(ERR, "New monitor has no name?? Ignoring");
return;
}
if (g_pCompositor->getMonitorFromName(std::string(OUTPUT->name))) {
Debug::log(WARN, "Monitor with name %s already exists, not adding as new!", OUTPUT->name);
return;
}
// get monitor rule that matches // get monitor rule that matches
SMonitorRule monitorRule = g_pConfigManager->getMonitorRuleFor(OUTPUT->name); SMonitorRule monitorRule = g_pConfigManager->getMonitorRuleFor(OUTPUT->name);
@@ -55,12 +65,16 @@ void Events::listener_newOutput(wl_listener* listener, void* data) {
if (monitorRule.disabled) { if (monitorRule.disabled) {
wlr_output_enable(OUTPUT, 0); wlr_output_enable(OUTPUT, 0);
wlr_output_commit(OUTPUT); wlr_output_commit(OUTPUT);
if (const auto PMONITOR = g_pCompositor->getMonitorFromName(std::string(OUTPUT->name)); PMONITOR) {
listener_monitorDestroy(nullptr, PMONITOR->output);
}
return; return;
} }
SMonitor newMonitor; SMonitor newMonitor;
newMonitor.output = OUTPUT; newMonitor.output = OUTPUT;
newMonitor.ID = g_pCompositor->m_lMonitors.size(); newMonitor.ID = g_pCompositor->getNextAvailableMonitorID();
newMonitor.szName = OUTPUT->name; newMonitor.szName = OUTPUT->name;
wlr_output_init_render(OUTPUT, g_pCompositor->m_sWLRAllocator, g_pCompositor->m_sWLRRenderer); wlr_output_init_render(OUTPUT, g_pCompositor->m_sWLRAllocator, g_pCompositor->m_sWLRRenderer);
@@ -101,17 +115,26 @@ void Events::listener_newOutput(wl_listener* listener, void* data) {
// Workspace // Workspace
const auto WORKSPACEID = monitorRule.defaultWorkspaceID == -1 ? g_pCompositor->m_lWorkspaces.size() + 1 /* Cuz workspaces doesnt have the new one yet and we start with 1 */ : monitorRule.defaultWorkspaceID; const auto WORKSPACEID = monitorRule.defaultWorkspaceID == -1 ? g_pCompositor->m_lWorkspaces.size() + 1 /* Cuz workspaces doesnt have the new one yet and we start with 1 */ : monitorRule.defaultWorkspaceID;
g_pCompositor->m_lWorkspaces.emplace_back(newMonitor.ID);
const auto PNEWWORKSPACE = &g_pCompositor->m_lWorkspaces.back(); auto PNEWWORKSPACE = g_pCompositor->getWorkspaceByID(WORKSPACEID);
// We are required to set the name here immediately Debug::log(LOG, "New monitor: WORKSPACEID %d, exists: %d", WORKSPACEID, (int)(PNEWWORKSPACE != nullptr));
wlr_ext_workspace_handle_v1_set_name(PNEWWORKSPACE->m_pWlrHandle, std::to_string(WORKSPACEID).c_str());
if (PNEWWORKSPACE) {
// workspace exists, move it to the newly connected monitor
g_pCompositor->moveWorkspaceToMonitor(PNEWWORKSPACE, PNEWMONITOR);
} else {
g_pCompositor->m_lWorkspaces.emplace_back(newMonitor.ID);
PNEWWORKSPACE = &g_pCompositor->m_lWorkspaces.back();
PNEWWORKSPACE->m_iID = WORKSPACEID; // We are required to set the name here immediately
PNEWWORKSPACE->m_szName = std::to_string(WORKSPACEID); wlr_ext_workspace_handle_v1_set_name(PNEWWORKSPACE->m_pWlrHandle, std::to_string(WORKSPACEID).c_str());
PNEWWORKSPACE->m_iID = WORKSPACEID;
PNEWWORKSPACE->m_szName = std::to_string(WORKSPACEID);
}
PNEWMONITOR->activeWorkspace = PNEWWORKSPACE->m_iID; PNEWMONITOR->activeWorkspace = PNEWWORKSPACE->m_iID;
PNEWMONITOR->scale = monitorRule.scale; PNEWMONITOR->scale = monitorRule.scale;
g_pCompositor->deactivateAllWLRWorkspaces(PNEWWORKSPACE->m_pWlrHandle); g_pCompositor->deactivateAllWLRWorkspaces(PNEWWORKSPACE->m_pWlrHandle);
@@ -122,7 +145,9 @@ void Events::listener_newOutput(wl_listener* listener, void* data) {
// //
if (!g_pCompositor->m_pLastMonitor) // set the last monitor if it isnt set yet if (!g_pCompositor->m_pLastMonitor) // set the last monitor if it isnt set yet
g_pCompositor->m_pLastMonitor = PNEWMONITOR; g_pCompositor->m_pLastMonitor = PNEWMONITOR;
g_pEventManager->postEvent(SHyprIPCEvent("monitoradded", PNEWMONITOR->szName));
// ready to process cuz we have a monitor // ready to process cuz we have a monitor
g_pCompositor->m_bReadyToProcess = true; g_pCompositor->m_bReadyToProcess = true;
@@ -131,6 +156,15 @@ void Events::listener_newOutput(wl_listener* listener, void* data) {
void Events::listener_monitorFrame(void* owner, void* data) { void Events::listener_monitorFrame(void* owner, void* data) {
SMonitor* const PMONITOR = (SMonitor*)owner; SMonitor* const PMONITOR = (SMonitor*)owner;
static std::chrono::high_resolution_clock::time_point startRender = std::chrono::high_resolution_clock::now();
static std::chrono::high_resolution_clock::time_point startRenderOverlay = std::chrono::high_resolution_clock::now();
static std::chrono::high_resolution_clock::time_point endRenderOverlay = std::chrono::high_resolution_clock::now();
if (g_pConfigManager->getInt("debug:overlay") == 1) {
startRender = std::chrono::high_resolution_clock::now();
g_pDebugOverlay->frameData(PMONITOR);
}
// Hack: only check when monitor with top hz refreshes, saves a bit of resources. // Hack: only check when monitor with top hz refreshes, saves a bit of resources.
// This is for stuff that should be run every frame // This is for stuff that should be run every frame
if (PMONITOR->ID == pMostHzMonitor->ID) { if (PMONITOR->ID == pMostHzMonitor->ID) {
@@ -146,9 +180,14 @@ void Events::listener_monitorFrame(void* owner, void* data) {
g_pConfigManager->performMonitorReload(); g_pConfigManager->performMonitorReload();
} }
if (PMONITOR->needsFrameSkip) { if (PMONITOR->framesToSkip > 0) {
PMONITOR->needsFrameSkip = false; PMONITOR->framesToSkip -= 1;
wlr_output_schedule_frame(PMONITOR->output);
if (!PMONITOR->noFrameSchedule)
wlr_output_schedule_frame(PMONITOR->output);
else {
Debug::log(LOG, "NoFrameSchedule hit for %s.", PMONITOR->szName.c_str());
}
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PMONITOR->ID); g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PMONITOR->ID);
return; return;
} }
@@ -182,7 +221,7 @@ void Events::listener_monitorFrame(void* owner, void* data) {
// if we have no tracking or full tracking, invalidate the entire monitor // if we have no tracking or full tracking, invalidate the entire monitor
if (DTMODE == DAMAGE_TRACKING_NONE || DTMODE == DAMAGE_TRACKING_MONITOR) { if (DTMODE == DAMAGE_TRACKING_NONE || DTMODE == DAMAGE_TRACKING_MONITOR) {
pixman_region32_union_rect(&damage, &damage, 0, 0, (int)PMONITOR->vecPixelSize.x, (int)PMONITOR->vecPixelSize.y); pixman_region32_union_rect(&damage, &damage, 0, 0, (int)PMONITOR->vecTransformedSize.x, (int)PMONITOR->vecTransformedSize.y);
pixman_region32_copy(&g_pHyprOpenGL->m_rOriginalDamageRegion, &damage); pixman_region32_copy(&g_pHyprOpenGL->m_rOriginalDamageRegion, &damage);
} else { } else {
@@ -213,6 +252,17 @@ void Events::listener_monitorFrame(void* owner, void* data) {
g_pHyprRenderer->renderAllClientsForMonitor(PMONITOR->ID, &now); g_pHyprRenderer->renderAllClientsForMonitor(PMONITOR->ID, &now);
// if correct monitor draw hyprerror
if (PMONITOR->ID == 0)
g_pHyprError->draw();
// for drawing the debug overlay
if (PMONITOR->ID == 0 && g_pConfigManager->getInt("debug:overlay") == 1) {
startRenderOverlay = std::chrono::high_resolution_clock::now();
g_pDebugOverlay->draw();
endRenderOverlay = std::chrono::high_resolution_clock::now();
}
wlr_renderer_begin(g_pCompositor->m_sWLRRenderer, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y); wlr_renderer_begin(g_pCompositor->m_sWLRRenderer, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y);
wlr_output_render_software_cursors(PMONITOR->output, NULL); wlr_output_render_software_cursors(PMONITOR->output, NULL);
@@ -226,10 +276,10 @@ void Events::listener_monitorFrame(void* owner, void* data) {
pixman_region32_init(&frameDamage); pixman_region32_init(&frameDamage);
const auto TRANSFORM = wlr_output_transform_invert(PMONITOR->output->transform); const auto TRANSFORM = wlr_output_transform_invert(PMONITOR->output->transform);
wlr_region_transform(&frameDamage, &PMONITOR->damage->current, TRANSFORM, (int)PMONITOR->vecPixelSize.x, (int)PMONITOR->vecPixelSize.y); wlr_region_transform(&frameDamage, &PMONITOR->damage->current, TRANSFORM, (int)PMONITOR->vecTransformedSize.x, (int)PMONITOR->vecTransformedSize.y);
if (DTMODE == DAMAGE_TRACKING_NONE || DTMODE == DAMAGE_TRACKING_MONITOR) if (DTMODE == DAMAGE_TRACKING_NONE || DTMODE == DAMAGE_TRACKING_MONITOR)
pixman_region32_union_rect(&frameDamage, &frameDamage, 0, 0, (int)PMONITOR->vecPixelSize.x, (int)PMONITOR->vecPixelSize.y); pixman_region32_union_rect(&frameDamage, &frameDamage, 0, 0, (int)PMONITOR->vecTransformedSize.x, (int)PMONITOR->vecTransformedSize.y);
wlr_output_set_damage(PMONITOR->output, &frameDamage); wlr_output_set_damage(PMONITOR->output, &frameDamage);
pixman_region32_fini(&frameDamage); pixman_region32_fini(&frameDamage);
@@ -238,6 +288,17 @@ void Events::listener_monitorFrame(void* owner, void* data) {
wlr_output_commit(PMONITOR->output); wlr_output_commit(PMONITOR->output);
wlr_output_schedule_frame(PMONITOR->output); wlr_output_schedule_frame(PMONITOR->output);
if (g_pConfigManager->getInt("debug:overlay") == 1) {
const float µs = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now() - startRender).count() / 1000.f;
g_pDebugOverlay->renderData(PMONITOR, µs);
if (PMONITOR->ID == 0) {
const float µsNoOverlay = µs - std::chrono::duration_cast<std::chrono::nanoseconds>(endRenderOverlay - startRenderOverlay).count() / 1000.f;
g_pDebugOverlay->renderDataNoOverlay(PMONITOR, µsNoOverlay);
} else {
g_pDebugOverlay->renderDataNoOverlay(PMONITOR, µs);
}
}
} }
void Events::listener_monitorDestroy(void* owner, void* data) { void Events::listener_monitorDestroy(void* owner, void* data) {
@@ -255,7 +316,58 @@ void Events::listener_monitorDestroy(void* owner, void* data) {
if (!pMonitor) if (!pMonitor)
return; return;
// Cleanup everything. Move windows back, snap cursor, shit.
const auto BACKUPMON = &g_pCompositor->m_lMonitors.front();
const auto BACKUPWORKSPACE = BACKUPMON->activeWorkspace > 0 ? std::to_string(BACKUPMON->activeWorkspace) : "name:" + g_pCompositor->getWorkspaceByID(BACKUPMON->activeWorkspace)->m_szName;
if (!BACKUPMON) {
Debug::log(CRIT, "No monitors! Unplugged last! Exiting.");
g_pCompositor->cleanupExit();
return;
}
// snap cursor
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sSeat.mouse->mouse, BACKUPMON->vecPosition.x + BACKUPMON->vecTransformedSize.x / 2.f, BACKUPMON->vecPosition.y + BACKUPMON->vecTransformedSize.y / 2.f);
// move workspaces
std::deque<CWorkspace*> wspToMove;
for (auto& w : g_pCompositor->m_lWorkspaces) {
if (w.m_iMonitorID == pMonitor->ID) {
wspToMove.push_back(&w);
}
}
for (auto& w : wspToMove) {
g_pCompositor->moveWorkspaceToMonitor(w, BACKUPMON);
w->startAnim(true, true, true);
}
pMonitor->activeWorkspace = -1;
for (auto it = g_pCompositor->m_lWorkspaces.begin(); it != g_pCompositor->m_lWorkspaces.end(); ++it) {
if (it->m_iMonitorID == pMonitor->ID) {
it = g_pCompositor->m_lWorkspaces.erase(it);
}
}
Debug::log(LOG, "Removed monitor %s!", pMonitor->szName.c_str());
g_pEventManager->postEvent(SHyprIPCEvent("monitorremoved", pMonitor->szName));
g_pCompositor->m_lMonitors.remove(*pMonitor); g_pCompositor->m_lMonitors.remove(*pMonitor);
// TODO: cleanup windows // update the pMostHzMonitor
if (pMostHzMonitor == pMonitor) {
int mostHz = 0;
SMonitor* pMonitorMostHz = nullptr;
for (auto& m : g_pCompositor->m_lMonitors) {
if (m.refreshRate > mostHz) {
pMonitorMostHz = &m;
mostHz = m.refreshRate;
}
}
pMostHzMonitor = pMonitorMostHz;
}
} }

View File

@@ -23,8 +23,8 @@ void addPopupGlobalCoords(void* pPopup, int* x, int* y) {
auto curPopup = PPOPUP; auto curPopup = PPOPUP;
while (true) { while (true) {
px += curPopup->popup->geometry.x; px += curPopup->popup->current.geometry.x;
py += curPopup->popup->geometry.y; py += curPopup->popup->current.geometry.y;
if (curPopup->parentPopup) { if (curPopup->parentPopup) {
curPopup = curPopup->parentPopup; curPopup = curPopup->parentPopup;
@@ -134,7 +134,7 @@ void Events::listener_mapPopupXDG(void* owner, void* data) {
Debug::log(LOG, "New XDG Popup mapped at %d %d", (int)PPOPUP->lx, (int)PPOPUP->ly); Debug::log(LOG, "New XDG Popup mapped at %d %d", (int)PPOPUP->lx, (int)PPOPUP->ly);
PPOPUP->pSurfaceTree = SubsurfaceTree::createTreeRoot(PPOPUP->popup->base->surface, addPopupGlobalCoords, PPOPUP); PPOPUP->pSurfaceTree = SubsurfaceTree::createTreeRoot(PPOPUP->popup->base->surface, addPopupGlobalCoords, PPOPUP, PPOPUP->parentWindow);
Debug::log(LOG, "XDG Popup got assigned a surfaceTreeNode %x", PPOPUP->pSurfaceTree); Debug::log(LOG, "XDG Popup got assigned a surfaceTreeNode %x", PPOPUP->pSurfaceTree);
} }

View File

@@ -25,16 +25,24 @@ void Events::listener_mapWindow(void* owner, void* data) {
CWindow* PWINDOW = (CWindow*)owner; CWindow* PWINDOW = (CWindow*)owner;
const auto PMONITOR = g_pCompositor->getMonitorFromCursor(); const auto PMONITOR = g_pCompositor->getMonitorFromCursor();
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(PMONITOR->activeWorkspace); const auto PWORKSPACE = PMONITOR->specialWorkspaceOpen ? g_pCompositor->getWorkspaceByID(SPECIAL_WORKSPACE_ID) : g_pCompositor->getWorkspaceByID(PMONITOR->activeWorkspace);
PWINDOW->m_iMonitorID = PMONITOR->ID; PWINDOW->m_iMonitorID = PMONITOR->ID;
PWINDOW->m_bMappedX11 = true; PWINDOW->m_bMappedX11 = true;
PWINDOW->m_iWorkspaceID = PMONITOR->activeWorkspace; PWINDOW->m_iWorkspaceID = PMONITOR->specialWorkspaceOpen ? SPECIAL_WORKSPACE_ID : PMONITOR->activeWorkspace;
PWINDOW->m_bIsMapped = true; PWINDOW->m_bIsMapped = true;
PWINDOW->m_bReadyToDelete = false; PWINDOW->m_bReadyToDelete = false;
PWINDOW->m_bFadingOut = false; PWINDOW->m_bFadingOut = false;
PWINDOW->m_szTitle = g_pXWaylandManager->getTitle(PWINDOW); PWINDOW->m_szTitle = g_pXWaylandManager->getTitle(PWINDOW);
PWINDOW->m_fAlpha = 255.f; PWINDOW->m_fAlpha = 255.f;
// Set all windows tiled regardless of anything
g_pXWaylandManager->setWindowStyleTiled(PWINDOW, WLR_EDGE_LEFT | WLR_EDGE_RIGHT | WLR_EDGE_TOP | WLR_EDGE_BOTTOM);
// Foreign Toplevel
PWINDOW->m_phForeignToplevel = wlr_foreign_toplevel_handle_v1_create(g_pCompositor->m_sWLRToplevelMgr);
// TODO: handle foreign events (requests)
wlr_foreign_toplevel_handle_v1_set_app_id(PWINDOW->m_phForeignToplevel, g_pXWaylandManager->getAppIDClass(PWINDOW).c_str());
// checks if the window wants borders and sets the appriopriate flag // checks if the window wants borders and sets the appriopriate flag
g_pXWaylandManager->checkBorders(PWINDOW); g_pXWaylandManager->checkBorders(PWINDOW);
@@ -62,22 +70,29 @@ void Events::listener_mapWindow(void* owner, void* data) {
if (PWORKSPACE->m_bHasFullscreenWindow && !PWINDOW->m_bIsFloating) { if (PWORKSPACE->m_bHasFullscreenWindow && !PWINDOW->m_bIsFloating) {
const auto PFULLWINDOW = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID); const auto PFULLWINDOW = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID);
g_pLayoutManager->getCurrentLayout()->fullscreenRequestForWindow(PFULLWINDOW); g_pLayoutManager->getCurrentLayout()->fullscreenRequestForWindow(PFULLWINDOW, FULLSCREEN_FULL);
g_pXWaylandManager->setWindowFullscreen(PFULLWINDOW, PFULLWINDOW->m_bIsFullscreen); g_pXWaylandManager->setWindowFullscreen(PFULLWINDOW, PFULLWINDOW->m_bIsFullscreen);
} }
// window rules // window rules
const auto WINDOWRULES = g_pConfigManager->getMatchingRules(PWINDOW); const auto WINDOWRULES = g_pConfigManager->getMatchingRules(PWINDOW);
std::string requestedWorkspace = "";
bool workspaceSilent = false;
for (auto& r : WINDOWRULES) { for (auto& r : WINDOWRULES) {
if (r.szRule.find("monitor") == 0) { if (r.szRule.find("monitor") == 0) {
try { try {
const long int MONITOR = std::stoi(r.szRule.substr(r.szRule.find(" "))); const auto MONITORSTR = r.szRule.substr(r.szRule.find(" "));
if (MONITOR >= (long int)g_pCompositor->m_lMonitors.size() || MONITOR < (long int)0) if (MONITORSTR == "unset") {
PWINDOW->m_iMonitorID = 0; PWINDOW->m_iMonitorID = PMONITOR->ID;
else } else {
PWINDOW->m_iMonitorID = MONITOR; const long int MONITOR = std::stoi(MONITORSTR);
if (MONITOR >= (long int)g_pCompositor->m_lMonitors.size() || MONITOR < (long int)0)
PWINDOW->m_iMonitorID = 0;
else
PWINDOW->m_iMonitorID = MONITOR;
}
PWINDOW->m_iWorkspaceID = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID)->activeWorkspace; PWINDOW->m_iWorkspaceID = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID)->activeWorkspace;
@@ -86,11 +101,14 @@ void Events::listener_mapWindow(void* owner, void* data) {
Debug::log(ERR, "Rule monitor failed, rule: %s -> %s | err: %s", r.szRule.c_str(), r.szValue.c_str(), e.what()); Debug::log(ERR, "Rule monitor failed, rule: %s -> %s | err: %s", r.szRule.c_str(), r.szValue.c_str(), e.what());
} }
} else if (r.szRule.find("workspace") == 0) { } else if (r.szRule.find("workspace") == 0) {
// switch to workspace // check if it isnt unset
g_pKeybindManager->m_mDispatchers["workspace"](r.szRule.substr(r.szRule.find_first_of(' ') + 1)); const auto WORKSPACERQ = r.szRule.substr(r.szRule.find_first_of(' ') + 1);
PWINDOW->m_iMonitorID = g_pCompositor->m_pLastMonitor->ID; if (WORKSPACERQ == "unset") {
PWINDOW->m_iWorkspaceID = g_pCompositor->m_pLastMonitor->activeWorkspace; requestedWorkspace = "";
} else {
requestedWorkspace = WORKSPACERQ;
}
Debug::log(LOG, "Rule workspace matched by window %x, %s applied.", PWINDOW, r.szValue.c_str()); Debug::log(LOG, "Rule workspace matched by window %x, %s applied.", PWINDOW, r.szValue.c_str());
} else if (r.szRule.find("float") == 0) { } else if (r.szRule.find("float") == 0) {
@@ -101,9 +119,23 @@ void Events::listener_mapWindow(void* owner, void* data) {
PWINDOW->m_bIsPseudotiled = true; PWINDOW->m_bIsPseudotiled = true;
} else if (r.szRule.find("nofocus") == 0) { } else if (r.szRule.find("nofocus") == 0) {
PWINDOW->m_bNoFocus = true; PWINDOW->m_bNoFocus = true;
} else if (r.szRule.find("rounding") == 0) {
try {
PWINDOW->m_sAdditionalConfigData.rounding = std::stoi(r.szRule.substr(r.szRule.find_first_of(' ') + 1));
} catch (std::exception& e) {
Debug::log(ERR, "Rounding rule \"%s\" failed with: %s", r.szRule.c_str(), e.what());
}
} else if (r.szRule.find("opacity") == 0) { } else if (r.szRule.find("opacity") == 0) {
try { try {
PWINDOW->m_sSpecialRenderData.alpha = std::stof(r.szRule.substr(r.szRule.find_first_of(' ') + 1)); std::string alphaPart = r.szRule.substr(r.szRule.find_first_of(' ') + 1);
if (alphaPart.find_first_of(' ') != std::string::npos) {
// we have a comma, 2 values
PWINDOW->m_sSpecialRenderData.alpha = std::stof(alphaPart.substr(0, alphaPart.find_first_of(' ')));
PWINDOW->m_sSpecialRenderData.alphaInactive = std::stof(alphaPart.substr(alphaPart.find_first_of(' ') + 1));
} else {
PWINDOW->m_sSpecialRenderData.alpha = std::stof(alphaPart);
}
} catch(std::exception& e) { } catch(std::exception& e) {
Debug::log(ERR, "Opacity rule \"%s\" failed with: %s", r.szRule.c_str(), e.what()); Debug::log(ERR, "Opacity rule \"%s\" failed with: %s", r.szRule.c_str(), e.what());
} }
@@ -113,6 +145,25 @@ void Events::listener_mapWindow(void* owner, void* data) {
} }
} }
if (requestedWorkspace != "") {
// process requested workspace
if (requestedWorkspace.find_first_of(' ') != std::string::npos) {
// check for silent
if (requestedWorkspace.find("silent") != std::string::npos) {
workspaceSilent = true;
}
requestedWorkspace = requestedWorkspace.substr(0, requestedWorkspace.find_first_of(' '));
}
if (!workspaceSilent) {
g_pKeybindManager->m_mDispatchers["workspace"](requestedWorkspace);
PWINDOW->m_iMonitorID = g_pCompositor->m_pLastMonitor->ID;
PWINDOW->m_iWorkspaceID = g_pCompositor->m_pLastMonitor->activeWorkspace;
}
}
if (PWINDOW->m_bIsFloating) { if (PWINDOW->m_bIsFloating) {
g_pLayoutManager->getCurrentLayout()->onWindowCreatedFloating(PWINDOW); g_pLayoutManager->getCurrentLayout()->onWindowCreatedFloating(PWINDOW);
PWINDOW->m_bCreatedOverFullscreen = true; PWINDOW->m_bCreatedOverFullscreen = true;
@@ -167,7 +218,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
if (!PWINDOW->m_bNoFocus) if (!PWINDOW->m_bNoFocus)
g_pCompositor->focusWindow(PWINDOW); g_pCompositor->focusWindow(PWINDOW);
PWINDOW->m_pSurfaceTree = SubsurfaceTree::createTreeRoot(g_pXWaylandManager->getWindowSurface(PWINDOW), addViewCoords, PWINDOW); PWINDOW->m_pSurfaceTree = SubsurfaceTree::createTreeRoot(g_pXWaylandManager->getWindowSurface(PWINDOW), addViewCoords, PWINDOW, PWINDOW);
Debug::log(LOG, "Window got assigned a surfaceTreeNode %x", PWINDOW->m_pSurfaceTree); Debug::log(LOG, "Window got assigned a surfaceTreeNode %x", PWINDOW->m_pSurfaceTree);
@@ -184,7 +235,16 @@ void Events::listener_mapWindow(void* owner, void* data) {
} }
// do the animation thing // do the animation thing
g_pAnimationManager->onWindowPostCreate(PWINDOW); g_pAnimationManager->onWindowPostCreateClose(PWINDOW, false);
if (workspaceSilent) {
// move the window
if (g_pCompositor->m_pLastWindow == PWINDOW) {
g_pKeybindManager->m_mDispatchers["movetoworkspacesilent"](requestedWorkspace);
} else {
Debug::log(ERR, "Tried to set workspace silent rule to a nofocus window!");
}
}
Debug::log(LOG, "Map request dispatched, monitor %s, xywh: %f %f %f %f", PMONITOR->szName.c_str(), PWINDOW->m_vRealPosition.goalv().x, PWINDOW->m_vRealPosition.goalv().y, PWINDOW->m_vRealSize.goalv().x, PWINDOW->m_vRealSize.goalv().y); Debug::log(LOG, "Map request dispatched, monitor %s, xywh: %f %f %f %f", PMONITOR->szName.c_str(), PWINDOW->m_vRealPosition.goalv().x, PWINDOW->m_vRealPosition.goalv().y, PWINDOW->m_vRealSize.goalv().x, PWINDOW->m_vRealSize.goalv().y);
} }
@@ -244,6 +304,18 @@ void Events::listener_unmapWindow(void* owner, void* data) {
g_pCompositor->m_lWindowsFadingOut.push_back(PWINDOW); g_pCompositor->m_lWindowsFadingOut.push_back(PWINDOW);
g_pHyprRenderer->damageMonitor(g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID)); g_pHyprRenderer->damageMonitor(g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID));
// do the animation thing
PWINDOW->m_vOriginalClosedPos = PWINDOW->m_vRealPosition.vec();
PWINDOW->m_vOriginalClosedSize = PWINDOW->m_vRealSize.vec();
if (!PWINDOW->m_bX11DoesntWantBorders) // don't animate out if they weren't animated in.
PWINDOW->m_vRealPosition = PWINDOW->m_vRealPosition.vec() + Vector2D(0.01f, 0.01f); // it has to be animated, otherwise onWindowPostCreateClose will ignore it
g_pAnimationManager->onWindowPostCreateClose(PWINDOW, true);
// Destroy Foreign Toplevel
wlr_foreign_toplevel_handle_v1_destroy(PWINDOW->m_phForeignToplevel);
PWINDOW->m_phForeignToplevel = nullptr;
} }
void Events::listener_commitWindow(void* owner, void* data) { void Events::listener_commitWindow(void* owner, void* data) {
@@ -291,6 +363,9 @@ void Events::listener_setTitleWindow(void* owner, void* data) {
if (PWINDOW == g_pCompositor->m_pLastWindow) // if it's the active, let's post an event to update others if (PWINDOW == g_pCompositor->m_pLastWindow) // if it's the active, let's post an event to update others
g_pEventManager->postEvent(SHyprIPCEvent("activewindow", g_pXWaylandManager->getAppIDClass(PWINDOW) + "," + PWINDOW->m_szTitle)); g_pEventManager->postEvent(SHyprIPCEvent("activewindow", g_pXWaylandManager->getAppIDClass(PWINDOW) + "," + PWINDOW->m_szTitle));
if (PWINDOW->m_phForeignToplevel)
wlr_foreign_toplevel_handle_v1_set_title(PWINDOW->m_phForeignToplevel, PWINDOW->m_szTitle.c_str());
Debug::log(LOG, "Window %x set title to %s", PWINDOW, PWINDOW->m_szTitle.c_str()); Debug::log(LOG, "Window %x set title to %s", PWINDOW, PWINDOW->m_szTitle.c_str());
} }
@@ -301,9 +376,9 @@ void Events::listener_fullscreenWindow(void* owner, void* data) {
const auto REQUESTED = &PWINDOW->m_uSurface.xdg->toplevel->requested; const auto REQUESTED = &PWINDOW->m_uSurface.xdg->toplevel->requested;
if (REQUESTED->fullscreen != PWINDOW->m_bIsFullscreen) if (REQUESTED->fullscreen != PWINDOW->m_bIsFullscreen)
g_pLayoutManager->getCurrentLayout()->fullscreenRequestForWindow(PWINDOW); g_pLayoutManager->getCurrentLayout()->fullscreenRequestForWindow(PWINDOW, FULLSCREEN_FULL);
} else { } else {
g_pLayoutManager->getCurrentLayout()->fullscreenRequestForWindow(PWINDOW); g_pLayoutManager->getCurrentLayout()->fullscreenRequestForWindow(PWINDOW, FULLSCREEN_FULL);
} }
Debug::log(LOG, "Window %x fullscreen to %i", PWINDOW, PWINDOW->m_bIsFullscreen); Debug::log(LOG, "Window %x fullscreen to %i", PWINDOW, PWINDOW->m_bIsFullscreen);

View File

@@ -149,8 +149,6 @@ public:
return false; // unreachable return false; // unreachable
} }
private:
void warp() { void warp() {
switch (m_eVarType) { switch (m_eVarType) {
case AVARTYPE_FLOAT: { case AVARTYPE_FLOAT: {
@@ -170,6 +168,8 @@ private:
} }
} }
private:
Vector2D m_vValue = Vector2D(0,0); Vector2D m_vValue = Vector2D(0,0);
float m_fValue = 0; float m_fValue = 0;
CColor m_cValue; CColor m_cValue;

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) {
@@ -125,7 +144,10 @@ bool isDirection(const std::string& arg) {
int getWorkspaceIDFromString(const std::string& in, std::string& outName) { int getWorkspaceIDFromString(const std::string& in, std::string& outName) {
int result = INT_MAX; int result = INT_MAX;
if (in.find("name:") == 0) { if (in.find("special") == 0) {
outName = "special";
return SPECIAL_WORKSPACE_ID;
} else if (in.find("name:") == 0) {
const auto WORKSPACENAME = in.substr(in.find_first_of(':') + 1); const auto WORKSPACENAME = in.substr(in.find_first_of(':') + 1);
const auto WORKSPACE = g_pCompositor->getWorkspaceByName(WORKSPACENAME); const auto WORKSPACE = g_pCompositor->getWorkspaceByName(WORKSPACENAME);
if (!WORKSPACE) { if (!WORKSPACE) {
@@ -135,8 +157,59 @@ int getWorkspaceIDFromString(const std::string& in, std::string& outName) {
} }
outName = WORKSPACENAME; outName = WORKSPACENAME;
} else { } else {
result = std::clamp((int)getPlusMinusKeywordResult(in, g_pCompositor->m_pLastMonitor->activeWorkspace), 1, INT_MAX); if (in[0] == 'm') {
outName = std::to_string(result); // monitor relative
result = (int)getPlusMinusKeywordResult(in.substr(1), 0);
// result now has +/- what we should move on mon
int remains = (int)result;
int currentID = g_pCompositor->m_pLastMonitor->activeWorkspace;
int searchID = currentID;
while (remains != 0) {
if (remains < 0)
searchID--;
else
searchID++;
if (g_pCompositor->workspaceIDOutOfBounds(searchID)){
// means we need to wrap around
int lowestID = 99999;
int highestID = -99999;
for (auto& w : g_pCompositor->m_lWorkspaces) {
if (w.m_iID < lowestID)
lowestID = w.m_iID;
if (w.m_iID > highestID)
highestID = w.m_iID;
}
if (remains < 0)
searchID = highestID;
else
searchID = lowestID;
}
if (const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(searchID); PWORKSPACE && PWORKSPACE->m_iID != SPECIAL_WORKSPACE_ID) {
if (PWORKSPACE->m_iMonitorID == g_pCompositor->m_pLastMonitor->ID) {
currentID = PWORKSPACE->m_iID;
if (remains < 0)
remains++;
else
remains--;
}
}
}
result = currentID;
outName = g_pCompositor->getWorkspaceByID(currentID)->m_szName;
} else {
result = std::clamp((int)getPlusMinusKeywordResult(in, g_pCompositor->m_pLastMonitor->activeWorkspace), 1, INT_MAX);
outName = std::to_string(result);
}
} }
return result; return result;

View File

@@ -7,9 +7,10 @@
#include <array> #include <array>
struct SMonitor { struct SMonitor {
Vector2D vecPosition = Vector2D(0,0); Vector2D vecPosition = Vector2D(0,0);
Vector2D vecSize = Vector2D(0,0); Vector2D vecSize = Vector2D(0,0);
Vector2D vecPixelSize = Vector2D(0,0); Vector2D vecPixelSize = Vector2D(0,0);
Vector2D vecTransformedSize = Vector2D(0,0);
bool primary = false; bool primary = false;
@@ -26,7 +27,12 @@ struct SMonitor {
wlr_output* output = nullptr; wlr_output* output = nullptr;
float refreshRate = 60; float refreshRate = 60;
wlr_output_damage* damage = nullptr; wlr_output_damage* damage = nullptr;
bool needsFrameSkip = false; int framesToSkip = 0;
bool noFrameSchedule = false;
wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL;
// for the special workspace
bool specialWorkspaceOpen = false;
// Double-linked list because we need to have constant mem addresses for signals // Double-linked list because we need to have constant mem addresses for signals
// We have to store pointers and use raw new/delete because they might be moved between them // We have to store pointers and use raw new/delete because they might be moved between them

View File

@@ -20,12 +20,13 @@ void addSurfaceGlobalOffset(SSurfaceTreeNode* node, int* lx, int* ly) {
} }
} }
SSurfaceTreeNode* createTree(wlr_surface* pSurface) { SSurfaceTreeNode* createTree(wlr_surface* pSurface, CWindow* pWindow) {
SubsurfaceTree::surfaceTreeNodes.push_back(SSurfaceTreeNode()); SubsurfaceTree::surfaceTreeNodes.push_back(SSurfaceTreeNode());
const auto PNODE = &SubsurfaceTree::surfaceTreeNodes.back(); const auto PNODE = &SubsurfaceTree::surfaceTreeNodes.back();
PNODE->pSurface = pSurface; PNODE->pSurface = pSurface;
PNODE->pWindowOwner = pWindow;
PNODE->hyprListener_newSubsurface.initCallback(&pSurface->events.new_subsurface, &Events::listener_newSubsurfaceNode, PNODE, "SurfaceTreeNode"); PNODE->hyprListener_newSubsurface.initCallback(&pSurface->events.new_subsurface, &Events::listener_newSubsurfaceNode, PNODE, "SurfaceTreeNode");
PNODE->hyprListener_commit.initCallback(&pSurface->events.commit, &Events::listener_commitSubsurface, PNODE, "SurfaceTreeNode"); PNODE->hyprListener_commit.initCallback(&pSurface->events.commit, &Events::listener_commitSubsurface, PNODE, "SurfaceTreeNode");
@@ -42,16 +43,21 @@ SSurfaceTreeNode* createTree(wlr_surface* pSurface) {
return PNODE; return PNODE;
} }
SSurfaceTreeNode* createSubsurfaceNode(SSurfaceTreeNode* pParent, SSubsurface* pSubsurface, wlr_surface* surface) { SSurfaceTreeNode* createSubsurfaceNode(SSurfaceTreeNode* pParent, SSubsurface* pSubsurface, wlr_surface* surface, CWindow* pWindow) {
const auto PNODE = createTree(surface); const auto PNODE = createTree(surface, pWindow);
PNODE->pParent = pParent; PNODE->pParent = pParent;
PNODE->pSubsurface = pSubsurface; PNODE->pSubsurface = pSubsurface;
Debug::log(LOG, "Creating a subsurface Node! (pWindow: %x)", pWindow);
return PNODE; return PNODE;
} }
SSurfaceTreeNode* SubsurfaceTree::createTreeRoot(wlr_surface* pSurface, applyGlobalOffsetFn fn, void* data) { SSurfaceTreeNode* SubsurfaceTree::createTreeRoot(wlr_surface* pSurface, applyGlobalOffsetFn fn, void* data, CWindow* pWindow) {
const auto PNODE = createTree(pSurface); const auto PNODE = createTree(pSurface, pWindow);
Debug::log(LOG, "Creating a surfaceTree Root! (pWindow: %x)", pWindow);
PNODE->offsetfn = fn; PNODE->offsetfn = fn;
PNODE->globalOffsetData = data; PNODE->globalOffsetData = data;
@@ -83,6 +89,20 @@ void SubsurfaceTree::destroySurfaceTree(SSurfaceTreeNode* pNode) {
pNode->hyprListener_destroy.removeCallback(); pNode->hyprListener_destroy.removeCallback();
pNode->hyprListener_newSubsurface.removeCallback(); pNode->hyprListener_newSubsurface.removeCallback();
// damage
if (pNode->pSurface) {
wlr_box extents = {};
wlr_surface_get_extends(pNode->pSurface, &extents);
int lx = 0, ly = 0;
addSurfaceGlobalOffset(pNode, &lx, &ly);
extents.x += lx;
extents.y += ly;
g_pHyprRenderer->damageBox(&extents);
}
surfaceTreeNodes.remove(*pNode); surfaceTreeNodes.remove(*pNode);
Debug::log(LOG, "SurfaceTree Node removed"); Debug::log(LOG, "SurfaceTree Node removed");
@@ -120,6 +140,8 @@ void Events::listener_newSubsurfaceNode(void* owner, void* data) {
PNEWSUBSURFACE->hyprListener_unmap.initCallback(&PSUBSURFACE->events.unmap, &Events::listener_unmapSubsurface, PNEWSUBSURFACE, "Subsurface"); PNEWSUBSURFACE->hyprListener_unmap.initCallback(&PSUBSURFACE->events.unmap, &Events::listener_unmapSubsurface, PNEWSUBSURFACE, "Subsurface");
PNEWSUBSURFACE->hyprListener_destroy.initCallback(&PSUBSURFACE->events.destroy, &Events::listener_destroySubsurface, PNEWSUBSURFACE, "Subsurface"); PNEWSUBSURFACE->hyprListener_destroy.initCallback(&PSUBSURFACE->events.destroy, &Events::listener_destroySubsurface, PNEWSUBSURFACE, "Subsurface");
PNEWSUBSURFACE->pWindowOwner = pNode->pWindowOwner;
wlr_subsurface* existingWlrSubsurface; wlr_subsurface* existingWlrSubsurface;
wl_list_for_each(existingWlrSubsurface, &PSUBSURFACE->surface->current.subsurfaces_below, current.link) { wl_list_for_each(existingWlrSubsurface, &PSUBSURFACE->surface->current.subsurfaces_below, current.link) {
listener_newSubsurfaceNode(pNode, existingWlrSubsurface); listener_newSubsurfaceNode(pNode, existingWlrSubsurface);
@@ -134,7 +156,7 @@ void Events::listener_mapSubsurface(void* owner, void* data) {
Debug::log(LOG, "Subsurface %x mapped", subsurface->pSubsurface); Debug::log(LOG, "Subsurface %x mapped", subsurface->pSubsurface);
subsurface->pChild = createSubsurfaceNode(subsurface->pParent, subsurface, subsurface->pSubsurface->surface); subsurface->pChild = createSubsurfaceNode(subsurface->pParent, subsurface, subsurface->pSubsurface->surface, subsurface->pWindowOwner);
} }
void Events::listener_unmapSubsurface(void* owner, void* data) { void Events::listener_unmapSubsurface(void* owner, void* data) {
@@ -154,6 +176,8 @@ void Events::listener_unmapSubsurface(void* owner, void* data) {
extents.x += lx; extents.x += lx;
extents.y += ly; extents.y += ly;
g_pHyprRenderer->damageBox(&extents);
SubsurfaceTree::destroySurfaceTree(subsurface->pChild); SubsurfaceTree::destroySurfaceTree(subsurface->pChild);
subsurface->pChild = nullptr; subsurface->pChild = nullptr;
} }
@@ -162,6 +186,14 @@ void Events::listener_unmapSubsurface(void* owner, void* data) {
void Events::listener_commitSubsurface(void* owner, void* data) { void Events::listener_commitSubsurface(void* owner, void* data) {
SSurfaceTreeNode* pNode = (SSurfaceTreeNode*)owner; SSurfaceTreeNode* pNode = (SSurfaceTreeNode*)owner;
// no damaging if it's not visible
if (!g_pHyprRenderer->shouldRenderWindow(pNode->pWindowOwner)) {
if (g_pConfigManager->getInt("debug:log_damage"))
Debug::log(LOG, "Refusing to commit damage from %x because it's invisible.", pNode->pWindowOwner);
return;
}
int lx = 0, ly = 0; int lx = 0, ly = 0;
addSurfaceGlobalOffset(pNode, &lx, &ly); addSurfaceGlobalOffset(pNode, &lx, &ly);

View File

@@ -4,6 +4,7 @@
#include <list> #include <list>
struct SSubsurface; struct SSubsurface;
class CWindow;
typedef void (*applyGlobalOffsetFn)(void *, int *, int *); typedef void (*applyGlobalOffsetFn)(void *, int *, int *);
@@ -21,6 +22,7 @@ struct SSurfaceTreeNode {
applyGlobalOffsetFn offsetfn; applyGlobalOffsetFn offsetfn;
void *globalOffsetData; void *globalOffsetData;
CWindow* pWindowOwner = nullptr;
bool operator==(const SSurfaceTreeNode& rhs) { bool operator==(const SSurfaceTreeNode& rhs) {
return pSurface == rhs.pSurface; return pSurface == rhs.pSurface;
@@ -37,13 +39,15 @@ struct SSubsurface {
DYNLISTENER(unmap); DYNLISTENER(unmap);
DYNLISTENER(destroy); DYNLISTENER(destroy);
CWindow* pWindowOwner = nullptr;
bool operator==(const SSubsurface& rhs) { bool operator==(const SSubsurface& rhs) {
return pSubsurface == rhs.pSubsurface; return pSubsurface == rhs.pSubsurface;
} }
}; };
namespace SubsurfaceTree { namespace SubsurfaceTree {
SSurfaceTreeNode* createTreeRoot(wlr_surface*, applyGlobalOffsetFn, void*); SSurfaceTreeNode* createTreeRoot(wlr_surface*, applyGlobalOffsetFn, void*, CWindow* pWindow = nullptr);
void destroySurfaceTree(SSurfaceTreeNode*); void destroySurfaceTree(SSurfaceTreeNode*);
inline std::list<SSurfaceTreeNode> surfaceTreeNodes; inline std::list<SSurfaceTreeNode> surfaceTreeNodes;

View File

@@ -57,6 +57,9 @@ struct SRenderData {
// for decorations (border) // for decorations (border)
bool decorate = false; bool decorate = false;
// for custom round values
int rounding = -1; // -1 means not set
}; };
struct SKeyboard { struct SKeyboard {
@@ -66,6 +69,8 @@ struct SKeyboard {
DYNLISTENER(keyboardKey); DYNLISTENER(keyboardKey);
DYNLISTENER(keyboardDestroy); DYNLISTENER(keyboardDestroy);
bool active = false;
// For the list lookup // For the list lookup
bool operator==(const SKeyboard& rhs) { bool operator==(const SKeyboard& rhs) {
return keyboard == rhs.keyboard; return keyboard == rhs.keyboard;

View File

@@ -1,7 +1,7 @@
#include "Workspace.hpp" #include "Workspace.hpp"
#include "../Compositor.hpp" #include "../Compositor.hpp"
CWorkspace::CWorkspace(int monitorID) { CWorkspace::CWorkspace(int monitorID, bool special) {
const auto PMONITOR = g_pCompositor->getMonitorFromID(monitorID); const auto PMONITOR = g_pCompositor->getMonitorFromID(monitorID);
if (!PMONITOR) { if (!PMONITOR) {
@@ -10,16 +10,20 @@ CWorkspace::CWorkspace(int monitorID) {
} }
m_iMonitorID = monitorID; m_iMonitorID = monitorID;
m_pWlrHandle = wlr_ext_workspace_handle_v1_create(PMONITOR->pWLRWorkspaceGroupHandle);
// set geometry here cuz we can m_bIsSpecialWorkspace = special;
wl_array_init(&m_wlrCoordinateArr);
*reinterpret_cast<int*>(wl_array_add(&m_wlrCoordinateArr, sizeof(int))) = (int)PMONITOR->vecPosition.x; if (!special) {
*reinterpret_cast<int*>(wl_array_add(&m_wlrCoordinateArr, sizeof(int))) = (int)PMONITOR->vecPosition.y; m_pWlrHandle = wlr_ext_workspace_handle_v1_create(PMONITOR->pWLRWorkspaceGroupHandle);
wlr_ext_workspace_handle_v1_set_coordinates(m_pWlrHandle, &m_wlrCoordinateArr);
wlr_ext_workspace_handle_v1_set_hidden(m_pWlrHandle, false); // set geometry here cuz we can
wlr_ext_workspace_handle_v1_set_urgent(m_pWlrHandle, false); wl_array_init(&m_wlrCoordinateArr);
*reinterpret_cast<int*>(wl_array_add(&m_wlrCoordinateArr, sizeof(int))) = (int)PMONITOR->vecPosition.x;
*reinterpret_cast<int*>(wl_array_add(&m_wlrCoordinateArr, sizeof(int))) = (int)PMONITOR->vecPosition.y;
wlr_ext_workspace_handle_v1_set_coordinates(m_pWlrHandle, &m_wlrCoordinateArr);
wlr_ext_workspace_handle_v1_set_hidden(m_pWlrHandle, false);
wlr_ext_workspace_handle_v1_set_urgent(m_pWlrHandle, false);
}
m_vRenderOffset.m_pWorkspace = this; m_vRenderOffset.m_pWorkspace = this;
m_vRenderOffset.create(AVARTYPE_VECTOR, &g_pConfigManager->getConfigValuePtr("animations:workspaces_speed")->floatValue, &g_pConfigManager->getConfigValuePtr("animations:workspaces")->intValue, &g_pConfigManager->getConfigValuePtr("animations:workspaces_curve")->strValue, nullptr, AVARDAMAGE_ENTIRE); m_vRenderOffset.create(AVARTYPE_VECTOR, &g_pConfigManager->getConfigValuePtr("animations:workspaces_speed")->floatValue, &g_pConfigManager->getConfigValuePtr("animations:workspaces")->intValue, &g_pConfigManager->getConfigValuePtr("animations:workspaces_curve")->strValue, nullptr, AVARDAMAGE_ENTIRE);
@@ -31,6 +35,8 @@ CWorkspace::CWorkspace(int monitorID) {
CWorkspace::~CWorkspace() { CWorkspace::~CWorkspace() {
m_vRenderOffset.unregister(); m_vRenderOffset.unregister();
Debug::log(LOG, "Destroying workspace ID %d", m_iID);
if (m_pWlrHandle) { if (m_pWlrHandle) {
wlr_ext_workspace_handle_v1_set_active(m_pWlrHandle, false); wlr_ext_workspace_handle_v1_set_active(m_pWlrHandle, false);
wlr_ext_workspace_handle_v1_destroy(m_pWlrHandle); wlr_ext_workspace_handle_v1_destroy(m_pWlrHandle);
@@ -38,7 +44,7 @@ CWorkspace::~CWorkspace() {
} }
} }
void CWorkspace::startAnim(bool in, bool left) { void CWorkspace::startAnim(bool in, bool left, bool instant) {
const auto ANIMSTYLE = g_pConfigManager->getString("animations:workspaces_style"); const auto ANIMSTYLE = g_pConfigManager->getString("animations:workspaces_style");
if (ANIMSTYLE == "fade") { if (ANIMSTYLE == "fade") {
@@ -51,6 +57,18 @@ void CWorkspace::startAnim(bool in, bool left) {
m_fAlpha.setValueAndWarp(255.f); m_fAlpha.setValueAndWarp(255.f);
m_fAlpha = 0.f; m_fAlpha = 0.f;
} }
} else if (ANIMSTYLE == "slidevert") {
// fallback is slide
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
m_fAlpha.setValueAndWarp(255.f); // fix a bug, if switching from fade -> slide.
if (in) {
m_vRenderOffset.setValueAndWarp(Vector2D(0, left ? PMONITOR->vecSize.y : -PMONITOR->vecSize.y));
m_vRenderOffset = Vector2D(0, 0);
} else {
m_vRenderOffset = Vector2D(0, left ? -PMONITOR->vecSize.y : PMONITOR->vecSize.y);
}
} else { } else {
// fallback is slide // fallback is slide
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID); const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
@@ -64,10 +82,37 @@ void CWorkspace::startAnim(bool in, bool left) {
m_vRenderOffset = Vector2D(left ? -PMONITOR->vecSize.x : PMONITOR->vecSize.x, 0); m_vRenderOffset = Vector2D(left ? -PMONITOR->vecSize.x : PMONITOR->vecSize.x, 0);
} }
} }
if (instant) {
m_vRenderOffset.warp();
m_fAlpha.warp();
}
} }
void CWorkspace::setActive(bool on) { void CWorkspace::setActive(bool on) {
if (m_pWlrHandle) { if (m_pWlrHandle) {
wlr_ext_workspace_handle_v1_set_active(m_pWlrHandle, on); wlr_ext_workspace_handle_v1_set_active(m_pWlrHandle, on);
} }
}
void CWorkspace::moveToMonitor(const int& id) {
const auto PMONITOR = g_pCompositor->getMonitorFromID(id);
if (!PMONITOR || m_bIsSpecialWorkspace)
return;
wlr_ext_workspace_handle_v1_set_active(m_pWlrHandle, false);
wlr_ext_workspace_handle_v1_destroy(m_pWlrHandle);
m_pWlrHandle = wlr_ext_workspace_handle_v1_create(PMONITOR->pWLRWorkspaceGroupHandle);
// set geometry here cuz we can
wl_array_init(&m_wlrCoordinateArr);
*reinterpret_cast<int*>(wl_array_add(&m_wlrCoordinateArr, sizeof(int))) = (int)PMONITOR->vecPosition.x;
*reinterpret_cast<int*>(wl_array_add(&m_wlrCoordinateArr, sizeof(int))) = (int)PMONITOR->vecPosition.y;
wlr_ext_workspace_handle_v1_set_coordinates(m_pWlrHandle, &m_wlrCoordinateArr);
wlr_ext_workspace_handle_v1_set_hidden(m_pWlrHandle, false);
wlr_ext_workspace_handle_v1_set_urgent(m_pWlrHandle, false);
wlr_ext_workspace_handle_v1_set_name(m_pWlrHandle, m_szName.c_str());
} }

View File

@@ -3,9 +3,14 @@
#include "../defines.hpp" #include "../defines.hpp"
#include "AnimatedVariable.hpp" #include "AnimatedVariable.hpp"
enum eFullscreenMode : uint8_t {
FULLSCREEN_FULL = 0,
FULLSCREEN_MAXIMIZED
};
class CWorkspace { class CWorkspace {
public: public:
CWorkspace(int monitorID); CWorkspace(int monitorID, bool special = false);
~CWorkspace(); ~CWorkspace();
// Workspaces ID-based have IDs > 0 // Workspaces ID-based have IDs > 0
@@ -14,6 +19,7 @@ public:
std::string m_szName = ""; std::string m_szName = "";
uint64_t m_iMonitorID = -1; uint64_t m_iMonitorID = -1;
bool m_bHasFullscreenWindow = false; bool m_bHasFullscreenWindow = false;
eFullscreenMode m_efFullscreenMode = FULLSCREEN_FULL;
wlr_ext_workspace_handle_v1* m_pWlrHandle = nullptr; wlr_ext_workspace_handle_v1* m_pWlrHandle = nullptr;
@@ -23,10 +29,15 @@ public:
CAnimatedVariable m_vRenderOffset; CAnimatedVariable m_vRenderOffset;
CAnimatedVariable m_fAlpha; CAnimatedVariable m_fAlpha;
// "scratchpad"
bool m_bIsSpecialWorkspace = false;
// user-set // user-set
bool m_bDefaultFloating = false; bool m_bDefaultFloating = false;
bool m_bDefaultPseudo = false; bool m_bDefaultPseudo = false;
void startAnim(bool in, bool left); void startAnim(bool in, bool left, bool instant = false);
void setActive(bool on); void setActive(bool on);
void moveToMonitor(const int&);
}; };

View File

@@ -34,55 +34,56 @@
#define static #define static
extern "C" { extern "C" {
#include <wlr/backend.h> #include "../wlroots/include/wlr/backend.h"
#include <wlr/backend/libinput.h> #include "../wlroots/include/wlr/backend/libinput.h"
#include <wlr/render/allocator.h> #include "../wlroots/include/wlr/render/allocator.h"
#include <wlr/render/wlr_renderer.h> #include "../wlroots/include/wlr/render/wlr_renderer.h"
#include <wlr/types/wlr_compositor.h> #include "../wlroots/include/wlr/types/wlr_compositor.h"
#include <wlr/types/wlr_cursor.h> #include "../wlroots/include/wlr/types/wlr_cursor.h"
#include <wlr/types/wlr_data_control_v1.h> #include "../wlroots/include/wlr/types/wlr_data_control_v1.h"
#include <wlr/types/wlr_data_device.h> #include "../wlroots/include/wlr/types/wlr_data_device.h"
#include <wlr/types/wlr_export_dmabuf_v1.h> #include "../wlroots/include/wlr/types/wlr_export_dmabuf_v1.h"
#include <wlr/types/wlr_linux_dmabuf_v1.h> #include "../wlroots/include/wlr/types/wlr_linux_dmabuf_v1.h"
#include <wlr/types/wlr_gamma_control_v1.h> #include "../wlroots/include/wlr/types/wlr_gamma_control_v1.h"
#include <wlr/types/wlr_idle.h> #include "../wlroots/include/wlr/types/wlr_idle.h"
#include <wlr/types/wlr_input_device.h> #include "../wlroots/include/wlr/types/wlr_input_device.h"
#include <wlr/types/wlr_keyboard.h> #include "../wlroots/include/wlr/types/wlr_keyboard.h"
#include <wlr/types/wlr_layer_shell_v1.h> #include "../wlroots/include/wlr/types/wlr_layer_shell_v1.h"
#include <wlr/types/wlr_matrix.h> #include "../wlroots/include/wlr/types/wlr_matrix.h"
#include <wlr/types/wlr_output.h> #include "../wlroots/include/wlr/types/wlr_output.h"
#include <wlr/types/wlr_output_layout.h> #include "../wlroots/include/wlr/types/wlr_output_layout.h"
#include <wlr/types/wlr_output_management_v1.h> #include "../wlroots/include/wlr/types/wlr_output_management_v1.h"
#include <wlr/types/wlr_pointer.h> #include "../wlroots/include/wlr/types/wlr_pointer.h"
#include <wlr/types/wlr_presentation_time.h> #include "../wlroots/include/wlr/types/wlr_presentation_time.h"
#include <wlr/types/wlr_primary_selection.h> #include "../wlroots/include/wlr/types/wlr_primary_selection.h"
#include <wlr/types/wlr_primary_selection_v1.h> #include "../wlroots/include/wlr/types/wlr_primary_selection_v1.h"
#include <wlr/types/wlr_screencopy_v1.h> #include "../wlroots/include/wlr/types/wlr_screencopy_v1.h"
#include <wlr/types/wlr_seat.h> #include "../wlroots/include/wlr/types/wlr_seat.h"
#include <wlr/types/wlr_server_decoration.h> #include "../wlroots/include/wlr/types/wlr_server_decoration.h"
#include <wlr/types/wlr_viewporter.h> #include "../wlroots/include/wlr/types/wlr_viewporter.h"
#include <wlr/types/wlr_virtual_keyboard_v1.h> #include "../wlroots/include/wlr/types/wlr_virtual_keyboard_v1.h"
#include <wlr/types/wlr_xcursor_manager.h> #include "../wlroots/include/wlr/types/wlr_xcursor_manager.h"
#include <wlr/types/wlr_xdg_activation_v1.h> #include "../wlroots/include/wlr/types/wlr_xdg_activation_v1.h"
#include <wlr/types/wlr_xdg_decoration_v1.h> #include "../wlroots/include/wlr/types/wlr_xdg_decoration_v1.h"
#include <wlr/types/wlr_xdg_output_v1.h> #include "../wlroots/include/wlr/types/wlr_xdg_output_v1.h"
#include <wlr/types/wlr_xdg_shell.h> #include "../wlroots/include/wlr/types/wlr_xdg_shell.h"
#include <wlr/types/wlr_subcompositor.h> #include "../wlroots/include/wlr/types/wlr_subcompositor.h"
#include <wlr/types/wlr_scene.h> #include "../wlroots/include/wlr/types/wlr_scene.h"
#include <wlr/types/wlr_output_damage.h> #include "../wlroots/include/wlr/types/wlr_output_damage.h"
#include <wlr/types/wlr_input_inhibitor.h> #include "../wlroots/include/wlr/types/wlr_input_inhibitor.h"
#include <wlr/types/wlr_keyboard_shortcuts_inhibit_v1.h> #include "../wlroots/include/wlr/types/wlr_keyboard_shortcuts_inhibit_v1.h"
#include <wlr/types/wlr_virtual_pointer_v1.h> #include "../wlroots/include/wlr/types/wlr_virtual_pointer_v1.h"
#include <wlr/util/log.h> #include "../wlroots/include/wlr/types/wlr_foreign_toplevel_management_v1.h"
#include <wlr/xwayland.h> #include "../wlroots/include/wlr/util/log.h"
#include <wlr/util/region.h> #include "../wlroots/include/wlr/xwayland.h"
#include "../wlroots/include/wlr/util/region.h"
#include <xkbcommon/xkbcommon.h> #include <xkbcommon/xkbcommon.h>
#include <X11/Xproto.h> #include <X11/Xproto.h>
#include <wlr/render/egl.h> #include "../wlroots/include/wlr/render/egl.h"
#include <wlr/render/gles2.h> #include "../wlroots/include/wlr/render/gles2.h"
#include <wlr/render/wlr_texture.h> #include "../wlroots/include/wlr/render/wlr_texture.h"
#include <wlr/types/wlr_pointer_constraints_v1.h> #include "../wlroots/include/wlr/types/wlr_pointer_constraints_v1.h"
#include <wlr/types/wlr_relative_pointer_v1.h> #include "../wlroots/include/wlr/types/wlr_relative_pointer_v1.h"
} }
#undef class #undef class

View File

@@ -160,10 +160,22 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode) {
} }
} }
PWINDOW->m_vRealSize = calcSize; const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(PWINDOW->m_iWorkspaceID);
PWINDOW->m_vRealPosition = calcPos;
g_pXWaylandManager->setWindowSize(PWINDOW, calcSize); if (PWORKSPACE->m_bIsSpecialWorkspace) {
// if special, we adjust the coords a bit
static auto *const PSCALEFACTOR = &g_pConfigManager->getConfigValuePtr("dwindle:special_scale_factor")->floatValue;
PWINDOW->m_vRealPosition = calcPos + (calcSize - calcSize * *PSCALEFACTOR) / 2.f;
PWINDOW->m_vRealSize = calcSize * *PSCALEFACTOR;
g_pXWaylandManager->setWindowSize(PWINDOW, calcSize * *PSCALEFACTOR);
} else {
PWINDOW->m_vRealSize = calcSize;
PWINDOW->m_vRealPosition = calcPos;
g_pXWaylandManager->setWindowSize(PWINDOW, calcSize);
}
} }
void CHyprDwindleLayout::onWindowCreated(CWindow* pWindow) { void CHyprDwindleLayout::onWindowCreated(CWindow* pWindow) {
@@ -184,7 +196,7 @@ void CHyprDwindleLayout::onWindowCreated(CWindow* pWindow) {
SDwindleNodeData* OPENINGON; SDwindleNodeData* OPENINGON;
const auto MONFROMCURSOR = g_pCompositor->getMonitorFromCursor(); const auto MONFROMCURSOR = g_pCompositor->getMonitorFromCursor();
if (PMONITOR->ID == MONFROMCURSOR->ID && PNODE->workspaceID == PMONITOR->activeWorkspace) { if (PMONITOR->ID == MONFROMCURSOR->ID && (PNODE->workspaceID == PMONITOR->activeWorkspace || (PNODE->workspaceID == SPECIAL_WORKSPACE_ID && PMONITOR->specialWorkspaceOpen))) {
OPENINGON = getNodeFromWindow(g_pCompositor->vectorToWindowTiled(g_pInputManager->getMouseCoordsInternal())); OPENINGON = getNodeFromWindow(g_pCompositor->vectorToWindowTiled(g_pInputManager->getMouseCoordsInternal()));
// happens on reserved area // happens on reserved area
@@ -196,6 +208,11 @@ void CHyprDwindleLayout::onWindowCreated(CWindow* pWindow) {
Debug::log(LOG, "OPENINGON: %x, Workspace: %i, Monitor: %i", OPENINGON, PNODE->workspaceID, PMONITOR->ID); Debug::log(LOG, "OPENINGON: %x, Workspace: %i, Monitor: %i", OPENINGON, PNODE->workspaceID, PMONITOR->ID);
if (OPENINGON && OPENINGON->workspaceID != PNODE->workspaceID) {
// special workspace handling
OPENINGON = getFirstNodeOnWorkspace(PNODE->workspaceID);
}
// if it's the first, it's easy. Make it fullscreen. // if it's the first, it's easy. Make it fullscreen.
if (!OPENINGON || OPENINGON->pWindow == pWindow) { if (!OPENINGON || OPENINGON->pWindow == pWindow) {
PNODE->position = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft; PNODE->position = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft;
@@ -275,6 +292,10 @@ void CHyprDwindleLayout::onWindowCreated(CWindow* pWindow) {
if (OPENINGON->pGroupParent) { if (OPENINGON->pGroupParent) {
// means we opened on a group // means we opened on a group
// add the group deco
pWindow->m_dWindowDecorations.emplace_back(std::make_unique<CHyprGroupBarDecoration>(pWindow));
PNODE->pGroupParent = OPENINGON->pGroupParent; PNODE->pGroupParent = OPENINGON->pGroupParent;
PNODE->pGroupParent->groupMembers.push_back(PNODE); PNODE->pGroupParent->groupMembers.push_back(PNODE);
PNODE->pGroupParent->groupMemberActive = PNODE->pGroupParent->groupMembers.size() - 1; PNODE->pGroupParent->groupMemberActive = PNODE->pGroupParent->groupMembers.size() - 1;
@@ -352,6 +373,19 @@ void CHyprDwindleLayout::recalculateMonitor(const int& monid) {
const auto PMONITOR = g_pCompositor->getMonitorFromID(monid); const auto PMONITOR = g_pCompositor->getMonitorFromID(monid);
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(PMONITOR->activeWorkspace); const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(PMONITOR->activeWorkspace);
if (!PWORKSPACE)
return;
if (PMONITOR->specialWorkspaceOpen) {
const auto TOPNODE = getMasterNodeOnWorkspace(SPECIAL_WORKSPACE_ID);
if (TOPNODE && PMONITOR) {
TOPNODE->position = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft;
TOPNODE->size = PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight;
TOPNODE->recalcSizePosRecursive();
}
}
// Ignore any recalc events if we have a fullscreen window. // Ignore any recalc events if we have a fullscreen window.
if (PWORKSPACE->m_bHasFullscreenWindow) if (PWORKSPACE->m_bHasFullscreenWindow)
return; return;
@@ -420,6 +454,13 @@ void CHyprDwindleLayout::onBeginDragWindow() {
return; return;
} }
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(DRAGGINGWINDOW->m_iWorkspaceID);
if (PWORKSPACE->m_bHasFullscreenWindow) {
Debug::log(LOG, "Rejecting drag on a fullscreen workspace.");
return;
}
DRAGGINGWINDOW->m_bDraggingTiled = false; DRAGGINGWINDOW->m_bDraggingTiled = false;
if (!DRAGGINGWINDOW->m_bIsFloating) { if (!DRAGGINGWINDOW->m_bIsFloating) {
@@ -476,80 +517,7 @@ void CHyprDwindleLayout::onMouseMove(const Vector2D& mousePos) {
g_pXWaylandManager->setWindowSize(DRAGGINGWINDOW, DRAGGINGWINDOW->m_vRealSize.goalv()); g_pXWaylandManager->setWindowSize(DRAGGINGWINDOW, DRAGGINGWINDOW->m_vRealSize.goalv());
} else { } else {
// we need to adjust the splitratio resizeActiveWindow(TICKDELTA, DRAGGINGWINDOW);
// get some data about our window
const auto PNODE = getNodeFromWindow(DRAGGINGWINDOW);
const auto PMONITOR = g_pCompositor->getMonitorFromID(DRAGGINGWINDOW->m_iMonitorID);
const bool DISPLAYLEFT = STICKS(DRAGGINGWINDOW->m_vPosition.x, PMONITOR->vecPosition.x + PMONITOR->vecReservedTopLeft.x);
const bool DISPLAYRIGHT = STICKS(DRAGGINGWINDOW->m_vPosition.x + DRAGGINGWINDOW->m_vSize.x, PMONITOR->vecPosition.x + PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x);
const bool DISPLAYTOP = STICKS(DRAGGINGWINDOW->m_vPosition.y, PMONITOR->vecPosition.y + PMONITOR->vecReservedTopLeft.y);
const bool DISPLAYBOTTOM = STICKS(DRAGGINGWINDOW->m_vPosition.y + DRAGGINGWINDOW->m_vSize.y, PMONITOR->vecPosition.y + PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y);
// construct allowed movement
Vector2D allowedMovement = TICKDELTA;
if (DISPLAYLEFT && DISPLAYRIGHT)
allowedMovement.x = 0;
if (DISPLAYBOTTOM && DISPLAYTOP)
allowedMovement.y = 0;
// get the correct containers to apply splitratio to
const auto PPARENT = PNODE->pParent;
if (!PPARENT)
return; // the only window on a workspace, ignore
const bool PARENTSIDEBYSIDE = !PPARENT->splitTop;
// Get the parent's parent
auto PPARENT2 = PPARENT->pParent;
// No parent means we have only 2 windows, and thus one axis of freedom
if (!PPARENT2) {
if (PARENTSIDEBYSIDE) {
allowedMovement.x *= 2.f / PPARENT->size.x;
PPARENT->splitRatio = std::clamp(PPARENT->splitRatio + allowedMovement.x, (double)0.1f, (double)1.9f);
PPARENT->recalcSizePosRecursive();
} else {
allowedMovement.y *= 2.f / PPARENT->size.y;
PPARENT->splitRatio = std::clamp(PPARENT->splitRatio + allowedMovement.y, (double)0.1f, (double)1.9f);
PPARENT->recalcSizePosRecursive();
}
return;
}
// Get first parent with other split
while(PPARENT2 && PPARENT2->splitTop == !PARENTSIDEBYSIDE)
PPARENT2 = PPARENT2->pParent;
// no parent, one axis of freedom
if (!PPARENT2) {
if (PARENTSIDEBYSIDE) {
allowedMovement.x *= 2.f / PPARENT->size.x;
PPARENT->splitRatio = std::clamp(PPARENT->splitRatio + allowedMovement.x, (double)0.1f, (double)1.9f);
PPARENT->recalcSizePosRecursive();
} else {
allowedMovement.y *= 2.f / PPARENT->size.y;
PPARENT->splitRatio = std::clamp(PPARENT->splitRatio + allowedMovement.y, (double)0.1f, (double)1.9f);
PPARENT->recalcSizePosRecursive();
}
return;
}
// 2 axes of freedom
const auto SIDECONTAINER = PARENTSIDEBYSIDE ? PPARENT : PPARENT2;
const auto TOPCONTAINER = PARENTSIDEBYSIDE ? PPARENT2 : PPARENT;
allowedMovement.x *= 2.f / SIDECONTAINER->size.x;
allowedMovement.y *= 2.f / TOPCONTAINER->size.y;
SIDECONTAINER->splitRatio = std::clamp(SIDECONTAINER->splitRatio + allowedMovement.x, (double)0.1f, (double)1.9f);
TOPCONTAINER->splitRatio = std::clamp(TOPCONTAINER->splitRatio + allowedMovement.y, (double)0.1f, (double)1.9f);
SIDECONTAINER->recalcSizePosRecursive();
TOPCONTAINER->recalcSizePosRecursive();
} }
} }
@@ -567,6 +535,97 @@ void CHyprDwindleLayout::onMouseMove(const Vector2D& mousePos) {
g_pHyprRenderer->damageWindow(DRAGGINGWINDOW); g_pHyprRenderer->damageWindow(DRAGGINGWINDOW);
} }
void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, CWindow* pWindow) {
const auto PWINDOW = pWindow ? pWindow : g_pCompositor->m_pLastWindow;
if (!g_pCompositor->windowValidMapped(PWINDOW))
return;
const auto PNODE = getNodeFromWindow(PWINDOW);
if (!PNODE) {
PWINDOW->m_vRealSize.setValueAndWarp(PWINDOW->m_vRealSize.goalv() + pixResize);
PWINDOW->m_vRealSize.setValueAndWarp(Vector2D(std::clamp(PWINDOW->m_vRealSize.vec().x, (double)20, (double)999999), std::clamp(PWINDOW->m_vRealSize.vec().y, (double)20, (double)999999)));
g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goalv());
return;
}
// get some data about our window
const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID);
const bool DISPLAYLEFT = STICKS(PWINDOW->m_vPosition.x, PMONITOR->vecPosition.x + PMONITOR->vecReservedTopLeft.x);
const bool DISPLAYRIGHT = STICKS(PWINDOW->m_vPosition.x + PWINDOW->m_vSize.x, PMONITOR->vecPosition.x + PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x);
const bool DISPLAYTOP = STICKS(PWINDOW->m_vPosition.y, PMONITOR->vecPosition.y + PMONITOR->vecReservedTopLeft.y);
const bool DISPLAYBOTTOM = STICKS(PWINDOW->m_vPosition.y + PWINDOW->m_vSize.y, PMONITOR->vecPosition.y + PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y);
// construct allowed movement
Vector2D allowedMovement = pixResize;
if (DISPLAYLEFT && DISPLAYRIGHT)
allowedMovement.x = 0;
if (DISPLAYBOTTOM && DISPLAYTOP)
allowedMovement.y = 0;
// get the correct containers to apply splitratio to
const auto PPARENT = PNODE->pParent;
if (!PPARENT)
return; // the only window on a workspace, ignore
const bool PARENTSIDEBYSIDE = !PPARENT->splitTop;
// Get the parent's parent
auto PPARENT2 = PPARENT->pParent;
// No parent means we have only 2 windows, and thus one axis of freedom
if (!PPARENT2) {
if (PARENTSIDEBYSIDE) {
allowedMovement.x *= 2.f / PPARENT->size.x;
PPARENT->splitRatio = std::clamp(PPARENT->splitRatio + allowedMovement.x, (double)0.1f, (double)1.9f);
PPARENT->recalcSizePosRecursive();
} else {
allowedMovement.y *= 2.f / PPARENT->size.y;
PPARENT->splitRatio = std::clamp(PPARENT->splitRatio + allowedMovement.y, (double)0.1f, (double)1.9f);
PPARENT->recalcSizePosRecursive();
}
return;
}
// Get first parent with other split
while (PPARENT2 && PPARENT2->splitTop == !PARENTSIDEBYSIDE)
PPARENT2 = PPARENT2->pParent;
// no parent, one axis of freedom
if (!PPARENT2) {
if (PARENTSIDEBYSIDE) {
allowedMovement.x *= 2.f / PPARENT->size.x;
PPARENT->splitRatio = std::clamp(PPARENT->splitRatio + allowedMovement.x, (double)0.1f, (double)1.9f);
PPARENT->recalcSizePosRecursive();
} else {
allowedMovement.y *= 2.f / PPARENT->size.y;
PPARENT->splitRatio = std::clamp(PPARENT->splitRatio + allowedMovement.y, (double)0.1f, (double)1.9f);
PPARENT->recalcSizePosRecursive();
}
return;
}
// 2 axes of freedom
const auto SIDECONTAINER = PARENTSIDEBYSIDE ? PPARENT : PPARENT2;
const auto TOPCONTAINER = PARENTSIDEBYSIDE ? PPARENT2 : PPARENT;
allowedMovement.x *= 2.f / SIDECONTAINER->size.x;
allowedMovement.y *= 2.f / TOPCONTAINER->size.y;
SIDECONTAINER->splitRatio = std::clamp(SIDECONTAINER->splitRatio + allowedMovement.x, (double)0.1f, (double)1.9f);
TOPCONTAINER->splitRatio = std::clamp(TOPCONTAINER->splitRatio + allowedMovement.y, (double)0.1f, (double)1.9f);
SIDECONTAINER->recalcSizePosRecursive();
TOPCONTAINER->recalcSizePosRecursive();
}
void CHyprDwindleLayout::onWindowCreatedFloating(CWindow* pWindow) { void CHyprDwindleLayout::onWindowCreatedFloating(CWindow* pWindow) {
wlr_box desiredGeometry = {0}; wlr_box desiredGeometry = {0};
g_pXWaylandManager->getGeometryForWindow(pWindow, &desiredGeometry); g_pXWaylandManager->getGeometryForWindow(pWindow, &desiredGeometry);
@@ -616,7 +675,7 @@ void CHyprDwindleLayout::onWindowCreatedFloating(CWindow* pWindow) {
g_pCompositor->moveWindowToTop(pWindow); g_pCompositor->moveWindowToTop(pWindow);
} }
void CHyprDwindleLayout::fullscreenRequestForWindow(CWindow* pWindow) { void CHyprDwindleLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscreenMode fullscreenMode) {
if (!g_pCompositor->windowValidMapped(pWindow)) if (!g_pCompositor->windowValidMapped(pWindow))
return; return;
@@ -646,6 +705,8 @@ void CHyprDwindleLayout::fullscreenRequestForWindow(CWindow* pWindow) {
} else { } else {
// if it now got fullscreen, make it fullscreen // if it now got fullscreen, make it fullscreen
PWORKSPACE->m_efFullscreenMode = fullscreenMode;
// save position and size if floating // save position and size if floating
if (pWindow->m_bIsFloating) { if (pWindow->m_bIsFloating) {
pWindow->m_vPosition = pWindow->m_vRealPosition.vec(); pWindow->m_vPosition = pWindow->m_vRealPosition.vec();
@@ -653,8 +714,22 @@ void CHyprDwindleLayout::fullscreenRequestForWindow(CWindow* pWindow) {
} }
// apply new pos and size being monitors' box // apply new pos and size being monitors' box
pWindow->m_vRealPosition = PMONITOR->vecPosition; if (fullscreenMode == FULLSCREEN_FULL) {
pWindow->m_vRealSize = PMONITOR->vecSize; pWindow->m_vRealPosition = PMONITOR->vecPosition;
pWindow->m_vRealSize = PMONITOR->vecSize;
} else {
// This is a massive hack.
// We make a fake "only" node and apply
// To keep consistent with the settings without C+P code
SDwindleNodeData fakeNode;
fakeNode.pWindow = pWindow;
fakeNode.position = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft;
fakeNode.size = PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight;
fakeNode.workspaceID = pWindow->m_iWorkspaceID;
applyNodeDataToWindow(&fakeNode);
}
} }
g_pXWaylandManager->setWindowSize(pWindow, pWindow->m_vRealSize.goalv()); g_pXWaylandManager->setWindowSize(pWindow, pWindow->m_vRealSize.goalv());
@@ -693,6 +768,10 @@ void CHyprDwindleLayout::toggleWindowGroup(CWindow* pWindow) {
for (auto& node : PGROUPPARENT->groupMembers) { for (auto& node : PGROUPPARENT->groupMembers) {
node->pGroupParent = nullptr; node->pGroupParent = nullptr;
node->pWindow->m_cRealBorderColor.setValueAndWarp(INACTIVEBORDERCOL); // no anim here because they pop in node->pWindow->m_cRealBorderColor.setValueAndWarp(INACTIVEBORDERCOL); // no anim here because they pop in
for (auto& wd : node->pWindow->m_dWindowDecorations) {
wd->updateWindow(node->pWindow);
}
} }
PGROUPPARENT->groupMembers.clear(); PGROUPPARENT->groupMembers.clear();
@@ -725,6 +804,8 @@ void CHyprDwindleLayout::toggleWindowGroup(CWindow* pWindow) {
c->pGroupParent = PPARENT; c->pGroupParent = PPARENT;
c->pWindow->m_cRealBorderColor = GROUPINACTIVEBORDERCOL; c->pWindow->m_cRealBorderColor = GROUPINACTIVEBORDERCOL;
c->pWindow->m_dWindowDecorations.push_back(std::make_unique<CHyprGroupBarDecoration>(c->pWindow));
if (c->pWindow == g_pCompositor->m_pLastWindow) if (c->pWindow == g_pCompositor->m_pLastWindow)
c->pWindow->m_cRealBorderColor = CColor(g_pConfigManager->getInt("dwindle:col.group_border_active")); c->pWindow->m_cRealBorderColor = CColor(g_pConfigManager->getInt("dwindle:col.group_border_active"));
} }
@@ -735,7 +816,32 @@ void CHyprDwindleLayout::toggleWindowGroup(CWindow* pWindow) {
} }
} }
void CHyprDwindleLayout::switchGroupWindow(CWindow* pWindow) { std::deque<CWindow*> CHyprDwindleLayout::getGroupMembers(CWindow* pWindow) {
std::deque<CWindow*> result;
if (!g_pCompositor->windowExists(pWindow))
return result; // reject with empty
// get the node
const auto PNODE = getNodeFromWindow(pWindow);
if (!PNODE)
return result; // reject with empty
const auto PGROUPPARENT = PNODE->pGroupParent;
if (!PGROUPPARENT)
return result; // reject with empty
for (auto& node : PGROUPPARENT->groupMembers) {
result.push_back(node->pWindow);
}
return result;
}
void CHyprDwindleLayout::switchGroupWindow(CWindow* pWindow, bool forward) {
if (!g_pCompositor->windowValidMapped(pWindow)) if (!g_pCompositor->windowValidMapped(pWindow))
return; // reject return; // reject
@@ -747,13 +853,25 @@ void CHyprDwindleLayout::switchGroupWindow(CWindow* pWindow) {
if (!PNODE->pGroupParent) if (!PNODE->pGroupParent)
return; // reject return; // reject
PNODE->pGroupParent->groupMemberActive++; if (forward)
PNODE->pGroupParent->groupMemberActive++;
else
PNODE->pGroupParent->groupMemberActive--;
if (PNODE->pGroupParent->groupMemberActive < 0)
PNODE->pGroupParent->groupMemberActive = PNODE->pGroupParent->groupMembers.size() - 1;
if ((long unsigned int)PNODE->pGroupParent->groupMemberActive >= PNODE->pGroupParent->groupMembers.size()) if ((long unsigned int)PNODE->pGroupParent->groupMemberActive >= PNODE->pGroupParent->groupMembers.size())
PNODE->pGroupParent->groupMemberActive = 0; PNODE->pGroupParent->groupMemberActive = 0;
PNODE->pGroupParent->recalcSizePosRecursive(); PNODE->pGroupParent->recalcSizePosRecursive();
for (auto& gm : PNODE->pGroupParent->groupMembers) {
for (auto& deco : gm->pWindow->m_dWindowDecorations) {
deco->updateWindow(gm->pWindow);
}
}
// focus // focus
g_pCompositor->focusWindow(PNODE->pGroupParent->groupMembers[PNODE->pGroupParent->groupMemberActive]->pWindow); g_pCompositor->focusWindow(PNODE->pGroupParent->groupMembers[PNODE->pGroupParent->groupMemberActive]->pWindow);
} }
@@ -844,13 +962,21 @@ void CHyprDwindleLayout::alterSplitRatioBy(CWindow* pWindow, float ratio) {
PNODE->pParent->recalcSizePosRecursive(); PNODE->pParent->recalcSizePosRecursive();
} }
void CHyprDwindleLayout::layoutMessage(SLayoutMessageHeader header, std::string message) { std::any CHyprDwindleLayout::layoutMessage(SLayoutMessageHeader header, std::string message) {
if (message == "togglegroup") if (message == "togglegroup")
toggleWindowGroup(header.pWindow); toggleWindowGroup(header.pWindow);
else if (message == "changegroupactive") else if (message == "changegroupactivef")
switchGroupWindow(header.pWindow); switchGroupWindow(header.pWindow, true);
else if (message == "changegroupactiveb")
switchGroupWindow(header.pWindow, false);
else if (message == "togglesplit") else if (message == "togglesplit")
toggleSplit(header.pWindow); toggleSplit(header.pWindow);
else if (message == "groupinfo") {
auto res = getGroupMembers(g_pCompositor->m_pLastWindow);
return res;
}
return "";
} }
void CHyprDwindleLayout::toggleSplit(CWindow* pWindow) { void CHyprDwindleLayout::toggleSplit(CWindow* pWindow) {
@@ -862,4 +988,8 @@ void CHyprDwindleLayout::toggleSplit(CWindow* pWindow) {
PNODE->pParent->splitTop = !PNODE->pParent->splitTop; PNODE->pParent->splitTop = !PNODE->pParent->splitTop;
PNODE->pParent->recalcSizePosRecursive(); PNODE->pParent->recalcSizePosRecursive();
}
std::string CHyprDwindleLayout::getLayoutName() {
return "dwindle";
} }

View File

@@ -3,8 +3,10 @@
#include "IHyprLayout.hpp" #include "IHyprLayout.hpp"
#include <list> #include <list>
#include <deque> #include <deque>
#include "../render/decorations/CHyprGroupBarDecoration.hpp"
class CHyprDwindleLayout; class CHyprDwindleLayout;
enum eFullscreenMode : uint8_t;
struct SDwindleNodeData { struct SDwindleNodeData {
SDwindleNodeData* pParent = nullptr; SDwindleNodeData* pParent = nullptr;
@@ -46,14 +48,16 @@ public:
virtual void recalculateWindow(CWindow*); virtual void recalculateWindow(CWindow*);
virtual void changeWindowFloatingMode(CWindow*); virtual void changeWindowFloatingMode(CWindow*);
virtual void onBeginDragWindow(); virtual void onBeginDragWindow();
virtual void resizeActiveWindow(const Vector2D&, CWindow* pWindow = nullptr);
virtual void onEndDragWindow(); virtual void onEndDragWindow();
virtual void onMouseMove(const Vector2D&); virtual void onMouseMove(const Vector2D&);
virtual void onWindowCreatedFloating(CWindow*); virtual void onWindowCreatedFloating(CWindow*);
virtual void fullscreenRequestForWindow(CWindow*); virtual void fullscreenRequestForWindow(CWindow*, eFullscreenMode);
virtual void layoutMessage(SLayoutMessageHeader, std::string); virtual std::any layoutMessage(SLayoutMessageHeader, std::string);
virtual SWindowRenderLayoutHints requestRenderHints(CWindow*); virtual SWindowRenderLayoutHints requestRenderHints(CWindow*);
virtual void switchWindows(CWindow*, CWindow*); virtual void switchWindows(CWindow*, CWindow*);
virtual void alterSplitRatioBy(CWindow*, float); virtual void alterSplitRatioBy(CWindow*, float);
virtual std::string getLayoutName();
private: private:
@@ -71,8 +75,9 @@ public:
SDwindleNodeData* getMasterNodeOnWorkspace(const int&); SDwindleNodeData* getMasterNodeOnWorkspace(const int&);
void toggleWindowGroup(CWindow*); void toggleWindowGroup(CWindow*);
void switchGroupWindow(CWindow*); void switchGroupWindow(CWindow*, bool forward);
void toggleSplit(CWindow*); void toggleSplit(CWindow*);
std::deque<CWindow*> getGroupMembers(CWindow*);
friend struct SDwindleNodeData; friend struct SDwindleNodeData;
}; };

View File

@@ -12,6 +12,8 @@ struct SLayoutMessageHeader {
CWindow* pWindow = nullptr; CWindow* pWindow = nullptr;
}; };
enum eFullscreenMode : uint8_t;
interface IHyprLayout { interface IHyprLayout {
public: public:
@@ -47,6 +49,12 @@ public:
as. as.
*/ */
virtual void onBeginDragWindow() = 0; virtual void onBeginDragWindow() = 0;
/*
Called when a user requests a resize of the current window by a vec
Vector2D holds pixel values
Optional pWindow for a specific window
*/
virtual void resizeActiveWindow(const Vector2D&, CWindow* pWindow = nullptr) = 0;
/* /*
Called when a window is ended being dragged Called when a window is ended being dragged
(mouse up) (mouse up)
@@ -66,17 +74,18 @@ public:
virtual void onWindowCreatedFloating(CWindow*) = 0; virtual void onWindowCreatedFloating(CWindow*) = 0;
/* /*
Called when a window requests to toggle its' fullscreen state. Called when a window / the user requests to toggle the fullscreen state of a window
The layout sets all the fullscreen flags. The layout sets all the fullscreen flags.
It can either accept or ignore. It can either accept or ignore.
*/ */
virtual void fullscreenRequestForWindow(CWindow*) = 0; virtual void fullscreenRequestForWindow(CWindow*, eFullscreenMode) = 0;
/* /*
Called when a dispatcher requests a custom message Called when a dispatcher requests a custom message
The layout is free to ignore. The layout is free to ignore.
std::any is the reply. Can be empty.
*/ */
virtual void layoutMessage(SLayoutMessageHeader, std::string) = 0; virtual std::any layoutMessage(SLayoutMessageHeader, std::string) = 0;
/* /*
Required to be handled, but may return just SWindowRenderLayoutHints() Required to be handled, but may return just SWindowRenderLayoutHints()
@@ -96,4 +105,9 @@ public:
on a window on a window
*/ */
virtual void alterSplitRatioBy(CWindow*, float) = 0; virtual void alterSplitRatioBy(CWindow*, float) = 0;
/*
Called when something wants the current layout's name
*/
virtual std::string getLayoutName() = 0;
}; };

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

@@ -140,8 +140,12 @@ void CAnimationManager::tick() {
case AVARDAMAGE_ENTIRE: { case AVARDAMAGE_ENTIRE: {
g_pHyprRenderer->damageBox(&WLRBOXPREV); g_pHyprRenderer->damageBox(&WLRBOXPREV);
if (PWINDOW) if (PWINDOW) {
g_pHyprRenderer->damageWindow(PWINDOW); g_pHyprRenderer->damageWindow(PWINDOW);
for (auto& wd : PWINDOW->m_dWindowDecorations) {
wd->updateWindow(PWINDOW);
}
}
break; break;
} }
case AVARDAMAGE_BORDER: { case AVARDAMAGE_BORDER: {
@@ -208,15 +212,20 @@ bool CAnimationManager::deltazero(const CColor& a, const CColor& b) {
// //
// //
void CAnimationManager::animationPopin(CWindow* pWindow) { void CAnimationManager::animationPopin(CWindow* pWindow, bool close) {
const auto GOALPOS = pWindow->m_vRealPosition.goalv(); const auto GOALPOS = pWindow->m_vRealPosition.goalv();
const auto GOALSIZE = pWindow->m_vRealSize.goalv(); const auto GOALSIZE = pWindow->m_vRealSize.goalv();
pWindow->m_vRealPosition.setValue(GOALPOS + GOALSIZE / 2.f); if (!close) {
pWindow->m_vRealSize.setValue(Vector2D(5, 5)); pWindow->m_vRealPosition.setValue(GOALPOS + GOALSIZE / 2.f);
pWindow->m_vRealSize.setValue(Vector2D(5, 5));
} else {
pWindow->m_vRealPosition = GOALPOS + GOALSIZE / 2.f;
pWindow->m_vRealSize = Vector2D(5, 5);
}
} }
void CAnimationManager::animationSlide(CWindow* pWindow, std::string force) { void CAnimationManager::animationSlide(CWindow* pWindow, std::string force, bool close) {
pWindow->m_vRealSize.warp(); // size we preserve in slide pWindow->m_vRealSize.warp(); // size we preserve in slide
const auto GOALPOS = pWindow->m_vRealPosition.goalv(); const auto GOALPOS = pWindow->m_vRealPosition.goalv();
@@ -224,11 +233,18 @@ void CAnimationManager::animationSlide(CWindow* pWindow, std::string force) {
const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID); const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID);
Vector2D posOffset;
if (force != "") { if (force != "") {
if (force == "bottom") pWindow->m_vRealPosition.setValue(Vector2D(GOALPOS.x, PMONITOR->vecPosition.y + PMONITOR->vecSize.y)); if (force == "bottom") posOffset = Vector2D(GOALPOS.x, PMONITOR->vecPosition.y + PMONITOR->vecSize.y);
else if (force == "left") pWindow->m_vRealPosition.setValue(GOALPOS - Vector2D(GOALSIZE.x, 0)); else if (force == "left") posOffset = GOALPOS - Vector2D(GOALSIZE.x, 0);
else if (force == "right") pWindow->m_vRealPosition.setValue(GOALPOS + Vector2D(GOALSIZE.x, 0)); else if (force == "right") posOffset = GOALPOS + Vector2D(GOALSIZE.x, 0);
else pWindow->m_vRealPosition.setValue(Vector2D(GOALPOS.x, PMONITOR->vecPosition.y - GOALSIZE.y)); else posOffset = Vector2D(GOALPOS.x, PMONITOR->vecPosition.y - GOALSIZE.y);
if (!close)
pWindow->m_vRealPosition.setValue(posOffset);
else
pWindow->m_vRealPosition = posOffset;
return; return;
} }
@@ -243,25 +259,30 @@ void CAnimationManager::animationSlide(CWindow* pWindow, std::string force) {
if (DISPLAYBOTTOM && DISPLAYTOP) { if (DISPLAYBOTTOM && DISPLAYTOP) {
if (DISPLAYLEFT && DISPLAYRIGHT) { if (DISPLAYLEFT && DISPLAYRIGHT) {
pWindow->m_vRealPosition.setValue(GOALPOS + Vector2D(0, GOALSIZE.y)); posOffset = GOALPOS + Vector2D(0, GOALSIZE.y);
} else if (DISPLAYLEFT) { } else if (DISPLAYLEFT) {
pWindow->m_vRealPosition.setValue(GOALPOS - Vector2D(GOALSIZE.x, 0)); posOffset = GOALPOS - Vector2D(GOALSIZE.x, 0);
} else { } else {
pWindow->m_vRealPosition.setValue(GOALPOS + Vector2D(GOALSIZE.x, 0)); posOffset = GOALPOS + Vector2D(GOALSIZE.x, 0);
} }
} else if (DISPLAYTOP) { } else if (DISPLAYTOP) {
pWindow->m_vRealPosition.setValue(GOALPOS - Vector2D(0, GOALSIZE.y)); posOffset = GOALPOS - Vector2D(0, GOALSIZE.y);
} else if (DISPLAYBOTTOM) { } else if (DISPLAYBOTTOM) {
pWindow->m_vRealPosition.setValue(GOALPOS + Vector2D(0, GOALSIZE.y)); posOffset = GOALPOS + Vector2D(0, GOALSIZE.y);
} else { } else {
if (MIDPOINT.y > PMONITOR->vecPosition.y + PMONITOR->vecSize.y / 2.f) if (MIDPOINT.y > PMONITOR->vecPosition.y + PMONITOR->vecSize.y / 2.f)
pWindow->m_vRealPosition.setValue(Vector2D(GOALPOS.x, PMONITOR->vecPosition.y + PMONITOR->vecSize.y)); posOffset = Vector2D(GOALPOS.x, PMONITOR->vecPosition.y + PMONITOR->vecSize.y);
else else
pWindow->m_vRealPosition.setValue(Vector2D(GOALPOS.x, PMONITOR->vecPosition.y - GOALSIZE.y)); posOffset = Vector2D(GOALPOS.x, PMONITOR->vecPosition.y - GOALSIZE.y);
} }
if (!close)
pWindow->m_vRealPosition.setValue(posOffset);
else
pWindow->m_vRealPosition = posOffset;
} }
void CAnimationManager::onWindowPostCreate(CWindow* pWindow) { void CAnimationManager::onWindowPostCreateClose(CWindow* pWindow, bool close) {
auto ANIMSTYLE = g_pConfigManager->getString("animations:windows_style"); auto ANIMSTYLE = g_pConfigManager->getString("animations:windows_style");
transform(ANIMSTYLE.begin(), ANIMSTYLE.end(), ANIMSTYLE.begin(), ::tolower); transform(ANIMSTYLE.begin(), ANIMSTYLE.end(), ANIMSTYLE.begin(), ::tolower);
@@ -274,20 +295,20 @@ void CAnimationManager::onWindowPostCreate(CWindow* pWindow) {
if (pWindow->m_sAdditionalConfigData.animationStyle.find("slide") == 0) { if (pWindow->m_sAdditionalConfigData.animationStyle.find("slide") == 0) {
if (pWindow->m_sAdditionalConfigData.animationStyle.find(' ') != std::string::npos) { if (pWindow->m_sAdditionalConfigData.animationStyle.find(' ') != std::string::npos) {
// has a direction // has a direction
animationSlide(pWindow, pWindow->m_sAdditionalConfigData.animationStyle.substr(pWindow->m_sAdditionalConfigData.animationStyle.find(' ') + 1)); animationSlide(pWindow, pWindow->m_sAdditionalConfigData.animationStyle.substr(pWindow->m_sAdditionalConfigData.animationStyle.find(' ') + 1), close);
} else { } else {
animationSlide(pWindow); animationSlide(pWindow, "", close);
} }
} else { } else {
// anim popin, fallback // anim popin, fallback
animationPopin(pWindow); animationPopin(pWindow, close);
} }
} else { } else {
if (ANIMSTYLE == "slide") { if (ANIMSTYLE == "slide") {
animationSlide(pWindow); animationSlide(pWindow, "", close);
} else { } else {
// anim popin, fallback // anim popin, fallback
animationPopin(pWindow); animationPopin(pWindow, close);
} }
} }
} }

View File

@@ -16,7 +16,7 @@ public:
void addBezierWithName(std::string, const Vector2D&, const Vector2D&); void addBezierWithName(std::string, const Vector2D&, const Vector2D&);
void removeAllBeziers(); void removeAllBeziers();
void onWindowPostCreate(CWindow*); void onWindowPostCreateClose(CWindow*, bool close = false);
std::list<CAnimatedVariable*> m_lAnimatedVariables; std::list<CAnimatedVariable*> m_lAnimatedVariables;
@@ -31,8 +31,8 @@ private:
std::unordered_map<std::string, CBezierCurve> m_mBezierCurves; std::unordered_map<std::string, CBezierCurve> m_mBezierCurves;
// Anim stuff // Anim stuff
void animationPopin(CWindow*); void animationPopin(CWindow*, bool close = false);
void animationSlide(CWindow*, std::string force = ""); void animationSlide(CWindow*, std::string force = "", bool close = false);
}; };
inline std::unique_ptr<CAnimationManager> g_pAnimationManager; inline std::unique_ptr<CAnimationManager> g_pAnimationManager;

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

@@ -5,12 +5,14 @@ void CInputManager::onMouseMoved(wlr_pointer_motion_event* e) {
float sensitivity = g_pConfigManager->getFloat("general:sensitivity"); float sensitivity = g_pConfigManager->getFloat("general:sensitivity");
if (g_pConfigManager->getInt("general:apply_sens_to_raw") == 1) const auto DELTA = g_pConfigManager->getInt("input:force_no_accel") == 1 ? Vector2D(e->unaccel_dx, e->unaccel_dy) : Vector2D(e->delta_x, e->delta_y);
wlr_relative_pointer_manager_v1_send_relative_motion(g_pCompositor->m_sWLRRelPointerMgr, g_pCompositor->m_sSeat.seat, (uint64_t)e->time_msec * 1000, e->delta_x * sensitivity, e->delta_y * sensitivity, e->unaccel_dx * sensitivity, e->unaccel_dy * sensitivity);
else
wlr_relative_pointer_manager_v1_send_relative_motion(g_pCompositor->m_sWLRRelPointerMgr, g_pCompositor->m_sSeat.seat, (uint64_t)e->time_msec * 1000, e->delta_x, e->delta_y, e->unaccel_dx, e->unaccel_dy);
wlr_cursor_move(g_pCompositor->m_sWLRCursor, &e->pointer->base, e->delta_x * sensitivity, e->delta_y * sensitivity); if (g_pConfigManager->getInt("general:apply_sens_to_raw") == 1)
wlr_relative_pointer_manager_v1_send_relative_motion(g_pCompositor->m_sWLRRelPointerMgr, g_pCompositor->m_sSeat.seat, (uint64_t)e->time_msec * 1000, DELTA.x * sensitivity, DELTA.y * sensitivity, e->unaccel_dx * sensitivity, e->unaccel_dy * sensitivity);
else
wlr_relative_pointer_manager_v1_send_relative_motion(g_pCompositor->m_sWLRRelPointerMgr, g_pCompositor->m_sSeat.seat, (uint64_t)e->time_msec * 1000, DELTA.x, DELTA.y, e->unaccel_dx, e->unaccel_dy);
wlr_cursor_move(g_pCompositor->m_sWLRCursor, &e->pointer->base, DELTA.x * sensitivity, DELTA.y * sensitivity);
mouseMoveUnified(e->time_msec); mouseMoveUnified(e->time_msec);
} }
@@ -105,7 +107,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
// then, we check if the workspace doesnt have a fullscreen window // then, we check if the workspace doesnt have a fullscreen window
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(PMONITOR->activeWorkspace); const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(PMONITOR->activeWorkspace);
if (PWORKSPACE->m_bHasFullscreenWindow && !foundSurface) { if (PWORKSPACE->m_bHasFullscreenWindow && !foundSurface && PWORKSPACE->m_efFullscreenMode == FULLSCREEN_FULL) {
pFoundWindow = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID); pFoundWindow = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID);
foundSurface = g_pXWaylandManager->getWindowSurface(pFoundWindow); foundSurface = g_pXWaylandManager->getWindowSurface(pFoundWindow);
surfacePos = pFoundWindow->m_vRealPosition.vec(); surfacePos = pFoundWindow->m_vRealPosition.vec();
@@ -113,7 +115,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
// only check floating because tiled cant be over fullscreen // only check floating because tiled cant be over fullscreen
for (auto w = g_pCompositor->m_lWindows.rbegin(); w != g_pCompositor->m_lWindows.rend(); w++) { for (auto w = g_pCompositor->m_lWindows.rbegin(); w != g_pCompositor->m_lWindows.rend(); w++) {
wlr_box box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y}; wlr_box box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y};
if (w->m_bIsFloating && w->m_bIsMapped && w->m_bCreatedOverFullscreen && wlr_box_contains_point(&box, mouseCoords.x, mouseCoords.y) && g_pCompositor->isWorkspaceVisible(w->m_iWorkspaceID) && !w->m_bHidden) { if (((w->m_bIsFloating && w->m_bIsMapped && w->m_bCreatedOverFullscreen) || (w->m_iWorkspaceID == SPECIAL_WORKSPACE_ID && PMONITOR->specialWorkspaceOpen)) && wlr_box_contains_point(&box, mouseCoords.x, mouseCoords.y) && g_pCompositor->isWorkspaceVisible(w->m_iWorkspaceID) && !w->m_bHidden) {
pFoundWindow = &(*w); pFoundWindow = &(*w);
if (!pFoundWindow->m_bIsX11) { if (!pFoundWindow->m_bIsX11) {
@@ -221,7 +223,6 @@ void CInputManager::onMouseButton(wlr_pointer_button_event* e) {
// notify app if we didnt handle it // notify app if we didnt handle it
if (g_pCompositor->doesSeatAcceptInput(g_pCompositor->m_pLastFocus)) { if (g_pCompositor->doesSeatAcceptInput(g_pCompositor->m_pLastFocus)) {
wlr_seat_pointer_notify_button(g_pCompositor->m_sSeat.seat, e->time_msec, e->button, e->state); wlr_seat_pointer_notify_button(g_pCompositor->m_sSeat.seat, e->time_msec, e->button, e->state);
Debug::log(LOG, "Seat notified of button %i (state %i) on surface %x", e->button, e->state, g_pCompositor->m_pLastFocus);
} }
} }
@@ -237,28 +238,24 @@ void CInputManager::newKeyboard(wlr_input_device* keyboard) {
PNEWKEYBOARD->keyboard = keyboard; PNEWKEYBOARD->keyboard = keyboard;
xkb_rule_names rules;
const auto CONTEXT = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
const auto KEYMAP = xkb_keymap_new_from_names(CONTEXT, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS);
const auto REPEATRATE = g_pConfigManager->getInt("input:repeat_rate"); const auto REPEATRATE = g_pConfigManager->getInt("input:repeat_rate");
const auto REPEATDELAY = g_pConfigManager->getInt("input:repeat_delay"); const auto REPEATDELAY = g_pConfigManager->getInt("input:repeat_delay");
wlr_keyboard_set_keymap(keyboard->keyboard, KEYMAP);
xkb_keymap_unref(KEYMAP);
xkb_context_unref(CONTEXT);
wlr_keyboard_set_repeat_info(keyboard->keyboard, std::max(0, REPEATRATE), std::max(0, REPEATDELAY)); wlr_keyboard_set_repeat_info(keyboard->keyboard, std::max(0, REPEATRATE), std::max(0, REPEATDELAY));
PNEWKEYBOARD->hyprListener_keyboardMod.initCallback(&keyboard->keyboard->events.modifiers, &Events::listener_keyboardMod, PNEWKEYBOARD, "Keyboard"); PNEWKEYBOARD->hyprListener_keyboardMod.initCallback(&keyboard->keyboard->events.modifiers, &Events::listener_keyboardMod, PNEWKEYBOARD, "Keyboard");
PNEWKEYBOARD->hyprListener_keyboardKey.initCallback(&keyboard->keyboard->events.key, &Events::listener_keyboardKey, PNEWKEYBOARD, "Keyboard"); PNEWKEYBOARD->hyprListener_keyboardKey.initCallback(&keyboard->keyboard->events.key, &Events::listener_keyboardKey, PNEWKEYBOARD, "Keyboard");
PNEWKEYBOARD->hyprListener_keyboardDestroy.initCallback(&keyboard->events.destroy, &Events::listener_keyboardDestroy, PNEWKEYBOARD, "Keyboard"); PNEWKEYBOARD->hyprListener_keyboardDestroy.initCallback(&keyboard->events.destroy, &Events::listener_keyboardDestroy, PNEWKEYBOARD, "Keyboard");
if (m_pActiveKeyboard)
m_pActiveKeyboard->active = false;
m_pActiveKeyboard = PNEWKEYBOARD;
setKeyboardLayout();
wlr_seat_set_keyboard(g_pCompositor->m_sSeat.seat, keyboard->keyboard); wlr_seat_set_keyboard(g_pCompositor->m_sSeat.seat, keyboard->keyboard);
Debug::log(LOG, "New keyboard created, pointers Hypr: %x and WLR: %x", PNEWKEYBOARD, keyboard); Debug::log(LOG, "New keyboard created, pointers Hypr: %x and WLR: %x", PNEWKEYBOARD, keyboard);
setKeyboardLayout();
} }
void CInputManager::setKeyboardLayout() { void CInputManager::setKeyboardLayout() {
@@ -286,9 +283,31 @@ void CInputManager::setKeyboardLayout() {
return; return;
} }
// TODO: configure devices one by one const auto PLASTKEEB = m_pActiveKeyboard->keyboard->keyboard;
for (auto& k : m_lKeyboards)
wlr_keyboard_set_keymap(k.keyboard->keyboard, KEYMAP); if (!PLASTKEEB) {
xkb_keymap_unref(KEYMAP);
xkb_context_unref(CONTEXT);
Debug::log(ERR, "No Seat Keyboard???");
return;
}
wlr_keyboard_set_keymap(PLASTKEEB, KEYMAP);
wlr_keyboard_modifiers wlrMods = {0};
if (g_pConfigManager->getInt("input:numlock_by_default") == 1) {
// lock numlock
const auto IDX = xkb_map_mod_get_index(KEYMAP, XKB_MOD_NAME_NUM);
if (IDX != XKB_MOD_INVALID)
wlrMods.locked |= (uint32_t)1 << IDX;
}
if (wlrMods.locked != 0) {
wlr_seat_keyboard_notify_modifiers(g_pCompositor->m_sSeat.seat, &wlrMods);
}
xkb_keymap_unref(KEYMAP); xkb_keymap_unref(KEYMAP);
xkb_context_unref(CONTEXT); xkb_context_unref(CONTEXT);
@@ -331,6 +350,17 @@ void CInputManager::destroyKeyboard(SKeyboard* pKeyboard) {
pKeyboard->hyprListener_keyboardMod.removeCallback(); pKeyboard->hyprListener_keyboardMod.removeCallback();
pKeyboard->hyprListener_keyboardKey.removeCallback(); pKeyboard->hyprListener_keyboardKey.removeCallback();
if (pKeyboard->active) {
m_lKeyboards.remove(*pKeyboard);
if (m_lKeyboards.size() > 0) {
m_pActiveKeyboard = &m_lKeyboards.back();
m_pActiveKeyboard->active = true;
} else {
m_pActiveKeyboard = nullptr;
}
}
m_lKeyboards.remove(*pKeyboard); m_lKeyboards.remove(*pKeyboard);
} }
@@ -360,8 +390,6 @@ void CInputManager::onKeyboardKey(wlr_keyboard_key_event* e, SKeyboard* pKeyboar
bool found = false; bool found = false;
if (e->state == WL_KEYBOARD_KEY_STATE_PRESSED) { if (e->state == WL_KEYBOARD_KEY_STATE_PRESSED) {
Debug::log(LOG, "Pressed key %i, with the MODMASK being %i", e->keycode, MODS);
for (int i = 0; i < syms; ++i) for (int i = 0; i < syms; ++i)
found = g_pKeybindManager->handleKeybinds(MODS, keysyms[i]) || found; found = g_pKeybindManager->handleKeybinds(MODS, keysyms[i]) || found;
} else if (e->state == WL_KEYBOARD_KEY_STATE_RELEASED) { } else if (e->state == WL_KEYBOARD_KEY_STATE_RELEASED) {

View File

@@ -36,12 +36,13 @@ public:
SDrag m_sDrag; SDrag m_sDrag;
std::list<SConstraint> m_lConstraints; std::list<SConstraint> m_lConstraints;
std::list<SKeyboard> m_lKeyboards;
std::list<SMouse> m_lMice;
private: SKeyboard* m_pActiveKeyboard = nullptr;
std::list<SKeyboard> m_lKeyboards; private:
std::list<SMouse> m_lMice;
void mouseMoveUnified(uint32_t, bool refocus = false); void mouseMoveUnified(uint32_t, bool refocus = false);
}; };

View File

@@ -20,6 +20,12 @@ CKeybindManager::CKeybindManager() {
m_mDispatchers["focusmonitor"] = focusMonitor; m_mDispatchers["focusmonitor"] = focusMonitor;
m_mDispatchers["movecursortocorner"] = moveCursorToCorner; m_mDispatchers["movecursortocorner"] = moveCursorToCorner;
m_mDispatchers["workspaceopt"] = workspaceOpt; m_mDispatchers["workspaceopt"] = workspaceOpt;
m_mDispatchers["exit"] = exitHyprland;
m_mDispatchers["movecurrentworkspacetomonitor"] = moveCurrentWorkspaceToMonitor;
m_mDispatchers["moveworkspacetomonitor"] = moveWorkspaceToMonitor;
m_mDispatchers["togglespecialworkspace"] = toggleSpecialWorkspace;
m_mDispatchers["forcerendererreload"] = forceRendererReload;
m_mDispatchers["resizeactive"] = resizeActive;
} }
void CKeybindManager::addKeybind(SKeybind kb) { void CKeybindManager::addKeybind(SKeybind kb) {
@@ -88,6 +94,7 @@ bool CKeybindManager::handleKeybinds(const uint32_t& modmask, const xkb_keysym_t
Debug::log(ERR, "Inavlid handler in a keybind! (handler %s does not exist)", k.handler.c_str()); Debug::log(ERR, "Inavlid handler in a keybind! (handler %s does not exist)", k.handler.c_str());
} else { } else {
// call the dispatcher // call the dispatcher
Debug::log(LOG, "Keybind triggered, calling dispatcher (%d, %d)", modmask, KBKEYUPPER);
DISPATCHER->second(k.arg); DISPATCHER->second(k.arg);
} }
@@ -104,8 +111,17 @@ bool CKeybindManager::handleInternalKeybinds(xkb_keysym_t keysym) {
const auto PSESSION = wlr_backend_get_session(g_pCompositor->m_sWLRBackend); const auto PSESSION = wlr_backend_get_session(g_pCompositor->m_sWLRBackend);
if (PSESSION) { if (PSESSION) {
const auto TTY = keysym - XKB_KEY_XF86Switch_VT_1 + 1; const int TTY = keysym - XKB_KEY_XF86Switch_VT_1 + 1;
wlr_session_change_vt(PSESSION, TTY); wlr_session_change_vt(PSESSION, TTY);
for (auto& m : g_pCompositor->m_lMonitors) {
g_pHyprOpenGL->destroyMonitorResources(&m); // mark resources as unusable anymore
m.noFrameSchedule = true;
m.framesToSkip = 2;
}
Debug::log(LOG, "Switched to VT %i, destroyed all render data, frames to skip for each: 2", TTY);
return true; return true;
} }
@@ -149,6 +165,10 @@ void CKeybindManager::toggleActiveFloating(std::string args) {
if (g_pCompositor->windowValidMapped(ACTIVEWINDOW)) { if (g_pCompositor->windowValidMapped(ACTIVEWINDOW)) {
ACTIVEWINDOW->m_bIsFloating = !ACTIVEWINDOW->m_bIsFloating; ACTIVEWINDOW->m_bIsFloating = !ACTIVEWINDOW->m_bIsFloating;
if (ACTIVEWINDOW->m_iWorkspaceID == SPECIAL_WORKSPACE_ID) {
moveActiveToWorkspace(std::to_string(g_pCompositor->getMonitorFromID(ACTIVEWINDOW->m_iMonitorID)->activeWorkspace));
}
ACTIVEWINDOW->m_vRealPosition.setValue(ACTIVEWINDOW->m_vRealPosition.vec() + Vector2D(5, 5)); ACTIVEWINDOW->m_vRealPosition.setValue(ACTIVEWINDOW->m_vRealPosition.vec() + Vector2D(5, 5));
ACTIVEWINDOW->m_vSize = ACTIVEWINDOW->m_vRealPosition.vec() - Vector2D(10, 10); ACTIVEWINDOW->m_vSize = ACTIVEWINDOW->m_vRealPosition.vec() - Vector2D(10, 10);
@@ -187,12 +207,20 @@ void CKeybindManager::changeworkspace(std::string args) {
const auto PWORKSPACETOCHANGETO = g_pCompositor->getWorkspaceByID(workspaceToChangeTo); const auto PWORKSPACETOCHANGETO = g_pCompositor->getWorkspaceByID(workspaceToChangeTo);
if (workspaceToChangeTo == SPECIAL_WORKSPACE_ID)
PWORKSPACETOCHANGETO->m_iMonitorID = PMONITOR->ID;
// if it's not visible, make it visible. // if it's not visible, make it visible.
if (!g_pCompositor->isWorkspaceVisible(workspaceToChangeTo)) { if (!g_pCompositor->isWorkspaceVisible(workspaceToChangeTo)) {
const auto OLDWORKSPACEID = PMONITOR->activeWorkspace; const auto OLDWORKSPACEID = PMONITOR->activeWorkspace;
// change it // change it
PMONITOR->activeWorkspace = workspaceToChangeTo; PMONITOR->specialWorkspaceOpen = false;
if (workspaceToChangeTo != SPECIAL_WORKSPACE_ID)
PMONITOR->activeWorkspace = workspaceToChangeTo;
else
PMONITOR->specialWorkspaceOpen = true;
// we need to move XWayland windows to narnia or otherwise they will still process our cursor and shit // we need to move XWayland windows to narnia or otherwise they will still process our cursor and shit
// and that'd be annoying as hell // and that'd be annoying as hell
@@ -215,7 +243,6 @@ void CKeybindManager::changeworkspace(std::string args) {
if (!m_bSuppressWorkspaceChangeEvents) if (!m_bSuppressWorkspaceChangeEvents)
g_pEventManager->postEvent(SHyprIPCEvent("workspace", PWORKSPACETOCHANGETO->m_szName)); g_pEventManager->postEvent(SHyprIPCEvent("workspace", PWORKSPACETOCHANGETO->m_szName));
} }
// If the monitor is not the one our cursor's at, warp to it. // If the monitor is not the one our cursor's at, warp to it.
if (PMONITOR != g_pCompositor->getMonitorFromCursor()) { if (PMONITOR != g_pCompositor->getMonitorFromCursor()) {
@@ -230,6 +257,9 @@ void CKeybindManager::changeworkspace(std::string args) {
g_pCompositor->deactivateAllWLRWorkspaces(PWORKSPACETOCHANGETO->m_pWlrHandle); g_pCompositor->deactivateAllWLRWorkspaces(PWORKSPACETOCHANGETO->m_pWlrHandle);
PWORKSPACETOCHANGETO->setActive(true); PWORKSPACETOCHANGETO->setActive(true);
// recalc layout
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PWORKSPACETOCHANGETO->m_iMonitorID);
Debug::log(LOG, "Changed to workspace %i", workspaceToChangeTo); Debug::log(LOG, "Changed to workspace %i", workspaceToChangeTo);
// focus // focus
@@ -250,22 +280,29 @@ void CKeybindManager::changeworkspace(std::string args) {
const auto ANIMTOLEFT = workspaceToChangeTo > OLDWORKSPACE; const auto ANIMTOLEFT = workspaceToChangeTo > OLDWORKSPACE;
// start anim on old workspace // start anim on old workspace
g_pCompositor->getWorkspaceByID(OLDWORKSPACE)->startAnim(false, ANIMTOLEFT); if (const auto POLDWORKSPACE = g_pCompositor->getWorkspaceByID(OLDWORKSPACE); POLDWORKSPACE)
POLDWORKSPACE->startAnim(false, ANIMTOLEFT);
g_pCompositor->m_lWorkspaces.emplace_back(PMONITOR->ID); g_pCompositor->m_lWorkspaces.emplace_back(PMONITOR->ID, workspaceToChangeTo == SPECIAL_WORKSPACE_ID);
const auto PWORKSPACE = &g_pCompositor->m_lWorkspaces.back(); const auto PWORKSPACE = &g_pCompositor->m_lWorkspaces.back();
// start anim on new workspace // start anim on new workspace
PWORKSPACE->startAnim(true, ANIMTOLEFT); PWORKSPACE->startAnim(true, ANIMTOLEFT);
// We are required to set the name here immediately // We are required to set the name here immediately
wlr_ext_workspace_handle_v1_set_name(PWORKSPACE->m_pWlrHandle, workspaceName.c_str()); if (workspaceToChangeTo != SPECIAL_WORKSPACE_ID)
wlr_ext_workspace_handle_v1_set_name(PWORKSPACE->m_pWlrHandle, workspaceName.c_str());
PWORKSPACE->m_iID = workspaceToChangeTo; PWORKSPACE->m_iID = workspaceToChangeTo;
PWORKSPACE->m_iMonitorID = PMONITOR->ID; PWORKSPACE->m_iMonitorID = PMONITOR->ID;
PWORKSPACE->m_szName = workspaceName; PWORKSPACE->m_szName = workspaceName;
PMONITOR->activeWorkspace = workspaceToChangeTo; PMONITOR->specialWorkspaceOpen = false;
if (workspaceToChangeTo != SPECIAL_WORKSPACE_ID)
PMONITOR->activeWorkspace = workspaceToChangeTo;
else
PMONITOR->specialWorkspaceOpen = true;
// we need to move XWayland windows to narnia or otherwise they will still process our cursor and shit // we need to move XWayland windows to narnia or otherwise they will still process our cursor and shit
// and that'd be annoying as hell // and that'd be annoying as hell
@@ -294,9 +331,9 @@ void CKeybindManager::fullscreenActive(std::string args) {
if (!g_pCompositor->windowValidMapped(PWINDOW)) if (!g_pCompositor->windowValidMapped(PWINDOW))
return; return;
g_pLayoutManager->getCurrentLayout()->fullscreenRequestForWindow(PWINDOW); g_pLayoutManager->getCurrentLayout()->fullscreenRequestForWindow(PWINDOW, args == "1" ? eFullscreenMode::FULLSCREEN_MAXIMIZED : eFullscreenMode::FULLSCREEN_FULL);
g_pXWaylandManager->setWindowFullscreen(PWINDOW, PWINDOW->m_bIsFullscreen); g_pXWaylandManager->setWindowFullscreen(PWINDOW, PWINDOW->m_bIsFullscreen && args == "0");
// make all windows on the same workspace under the fullscreen window // make all windows on the same workspace under the fullscreen window
for (auto& w : g_pCompositor->m_lWindows) { for (auto& w : g_pCompositor->m_lWindows) {
@@ -311,20 +348,33 @@ void CKeybindManager::moveActiveToWorkspace(std::string args) {
if (!g_pCompositor->windowValidMapped(PWINDOW)) if (!g_pCompositor->windowValidMapped(PWINDOW))
return; return;
g_pLayoutManager->getCurrentLayout()->onWindowRemoved(PWINDOW);
const auto OLDWORKSPACE = g_pCompositor->getWorkspaceByID(PWINDOW->m_iWorkspaceID); const auto OLDWORKSPACE = g_pCompositor->getWorkspaceByID(PWINDOW->m_iWorkspaceID);
// hack // hack
std::string unusedName;
const auto WORKSPACEID = getWorkspaceIDFromString(args, unusedName);
if (WORKSPACEID == PWINDOW->m_iWorkspaceID) {
Debug::log(LOG, "Not moving to workspace because it didn't change.");
return;
}
g_pLayoutManager->getCurrentLayout()->onWindowRemoved(PWINDOW);
g_pKeybindManager->changeworkspace(args); g_pKeybindManager->changeworkspace(args);
const auto PWORKSPACE = g_pCompositor->getWorkspaceByString(args); const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(WORKSPACEID);
if (PWORKSPACE == OLDWORKSPACE) { if (PWORKSPACE == OLDWORKSPACE) {
Debug::log(LOG, "Not moving to workspace because it didn't change."); Debug::log(LOG, "Not moving to workspace because it didn't change.");
return; return;
} }
if (!PWORKSPACE) {
Debug::log(ERR, "Workspace null in moveActiveToWorkspace?");
return;
}
OLDWORKSPACE->m_bHasFullscreenWindow = false; OLDWORKSPACE->m_bHasFullscreenWindow = false;
PWINDOW->m_iWorkspaceID = PWORKSPACE->m_iID; PWINDOW->m_iWorkspaceID = PWORKSPACE->m_iID;
@@ -352,6 +402,17 @@ void CKeybindManager::moveActiveToWorkspace(std::string args) {
PWINDOW->m_vRealPosition.setValue(PWINDOW->m_vRealPosition.vec() + g_pCompositor->getMonitorFromID(PWORKSPACE->m_iMonitorID)->vecPosition); PWINDOW->m_vRealPosition.setValue(PWINDOW->m_vRealPosition.vec() + g_pCompositor->getMonitorFromID(PWORKSPACE->m_iMonitorID)->vecPosition);
PWINDOW->m_vPosition = PWINDOW->m_vRealPosition.vec(); PWINDOW->m_vPosition = PWINDOW->m_vRealPosition.vec();
} }
// undo the damage if we are moving to the special workspace
if (WORKSPACEID == SPECIAL_WORKSPACE_ID) {
changeworkspace(std::to_string(OLDWORKSPACE->m_iID));
OLDWORKSPACE->startAnim(true, true, true);
toggleSpecialWorkspace("");
g_pCompositor->getWorkspaceByID(SPECIAL_WORKSPACE_ID)->startAnim(false, false, true);
for (auto& m : g_pCompositor->m_lMonitors)
m.specialWorkspaceOpen = false;
}
} }
void CKeybindManager::moveActiveToWorkspaceSilent(std::string args) { void CKeybindManager::moveActiveToWorkspaceSilent(std::string args) {
@@ -503,7 +564,10 @@ void CKeybindManager::toggleGroup(std::string args) {
void CKeybindManager::changeGroupActive(std::string args) { void CKeybindManager::changeGroupActive(std::string args) {
SLayoutMessageHeader header; SLayoutMessageHeader header;
header.pWindow = g_pCompositor->m_pLastWindow; header.pWindow = g_pCompositor->m_pLastWindow;
g_pLayoutManager->getCurrentLayout()->layoutMessage(header, "changegroupactive"); if (args == "b")
g_pLayoutManager->getCurrentLayout()->layoutMessage(header, "changegroupactiveb");
else
g_pLayoutManager->getCurrentLayout()->layoutMessage(header, "changegroupactivef");
} }
void CKeybindManager::toggleSplit(std::string args) { void CKeybindManager::toggleSplit(std::string args) {
@@ -558,7 +622,12 @@ void CKeybindManager::focusMonitor(std::string arg) {
if (isDirection(arg)) { if (isDirection(arg)) {
const auto PMONITOR = g_pCompositor->getMonitorInDirection(arg[0]); const auto PMONITOR = g_pCompositor->getMonitorInDirection(arg[0]);
if (PMONITOR) { if (PMONITOR) {
changeworkspace(std::to_string(PMONITOR->activeWorkspace)); if (PMONITOR->activeWorkspace < 0) {
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(PMONITOR->activeWorkspace);
changeworkspace("name:" + PWORKSPACE->m_szName);
}
else
changeworkspace(std::to_string(PMONITOR->activeWorkspace));
return; return;
} }
} else { } else {
@@ -666,4 +735,133 @@ void CKeybindManager::workspaceOpt(std::string args) {
// recalc mon // recalc mon
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(g_pCompositor->m_pLastMonitor->ID); g_pLayoutManager->getCurrentLayout()->recalculateMonitor(g_pCompositor->m_pLastMonitor->ID);
}
void CKeybindManager::exitHyprland(std::string argz) {
g_pCompositor->cleanupExit();
exit(0);
}
void CKeybindManager::moveCurrentWorkspaceToMonitor(std::string args) {
if (!isNumber(args) && !isDirection(args)) {
Debug::log(ERR, "moveCurrentWorkspaceToMonitor arg not a number or direction!");
return;
}
const auto PMONITOR = isDirection(args) ? g_pCompositor->getMonitorInDirection(args[0]) : g_pCompositor->getMonitorFromID(std::stoi(args));
if (!PMONITOR) {
Debug::log(ERR, "Ignoring moveCurrentWorkspaceToMonitor: monitor doesnt exist");
return;
}
// get the current workspace
const auto PCURRENTWORKSPACE = g_pCompositor->getWorkspaceByID(g_pCompositor->m_pLastMonitor->activeWorkspace);
if (!PCURRENTWORKSPACE)
return;
g_pCompositor->moveWorkspaceToMonitor(PCURRENTWORKSPACE, PMONITOR);
}
void CKeybindManager::moveWorkspaceToMonitor(std::string args) {
if (args.find_first_of(' ') == std::string::npos)
return;
std::string workspace = args.substr(0, args.find_first_of(' '));
std::string monitor = args.substr(args.find_first_of(' ') + 1);
if (!isNumber(monitor) && !isDirection(monitor)) {
Debug::log(ERR, "moveWorkspaceToMonitor monitor arg not a number or direction!");
return;
}
const auto PMONITOR = isDirection(monitor) ? g_pCompositor->getMonitorInDirection(monitor[0]) : g_pCompositor->getMonitorFromID(std::stoi(monitor));
if (!PMONITOR){
Debug::log(ERR, "Ignoring moveWorkspaceToMonitor: monitor doesnt exist");
return;
}
std::string workspaceName;
const int WORKSPACEID = getWorkspaceIDFromString(workspace, workspaceName);
if (WORKSPACEID == INT_MAX) {
Debug::log(ERR, "moveWorkspaceToMonitor invalid workspace!");
return;
}
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(WORKSPACEID);
if (!PWORKSPACE) {
Debug::log(ERR, "moveWorkspaceToMonitor workspace doesn't exist!");
return;
}
g_pCompositor->moveWorkspaceToMonitor(PWORKSPACE, PMONITOR);
}
void CKeybindManager::toggleSpecialWorkspace(std::string args) {
if (g_pCompositor->getWindowsOnWorkspace(SPECIAL_WORKSPACE_ID) == 0) {
Debug::log(LOG, "Can't open empty special workspace!");
return;
}
bool open = false;
for (auto& m : g_pCompositor->m_lMonitors) {
if (m.specialWorkspaceOpen) {
open = true;
break;
}
}
if (open)
Debug::log(LOG, "Toggling special workspace to closed");
else
Debug::log(LOG, "Toggling special workspace to open");
if (open) {
for (auto& m : g_pCompositor->m_lMonitors) {
if (m.specialWorkspaceOpen != !open) {
m.specialWorkspaceOpen = !open;
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m.ID);
g_pCompositor->getWorkspaceByID(SPECIAL_WORKSPACE_ID)->startAnim(false, false);
}
}
} else {
g_pCompositor->m_pLastMonitor->specialWorkspaceOpen = true;
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(g_pCompositor->m_pLastMonitor->ID);
g_pCompositor->getWorkspaceByID(SPECIAL_WORKSPACE_ID)->startAnim(true, true);
}
g_pInputManager->refocus();
}
void CKeybindManager::forceRendererReload(std::string args) {
for (auto& m : g_pCompositor->m_lMonitors) {
auto rule = g_pConfigManager->getMonitorRuleFor(m.szName);
g_pHyprRenderer->applyMonitorRule(&m, &rule, true);
}
}
void CKeybindManager::resizeActive(std::string args) {
if (args.find_first_of(' ') == std::string::npos)
return;
std::string x = args.substr(0, args.find_first_of(' '));
std::string y = args.substr(args.find_first_of(' ') + 1);
if (!isNumber(x) || !isNumber(y)) {
Debug::log(ERR, "resizeTiledWindow: args not numbers");
return;
}
const int X = std::stoi(x);
const int Y = std::stoi(y);
g_pLayoutManager->getCurrentLayout()->resizeActiveWindow(Vector2D(X, Y));
} }

View File

@@ -50,6 +50,14 @@ private:
static void toggleSplit(std::string); static void toggleSplit(std::string);
static void moveCursorToCorner(std::string); static void moveCursorToCorner(std::string);
static void workspaceOpt(std::string); static void workspaceOpt(std::string);
static void exitHyprland(std::string);
static void moveCurrentWorkspaceToMonitor(std::string);
static void moveWorkspaceToMonitor(std::string);
static void toggleSpecialWorkspace(std::string);
static void forceRendererReload(std::string);
static void resizeActive(std::string);
friend class CCompositor;
}; };
inline std::unique_ptr<CKeybindManager> g_pKeybindManager; inline std::unique_ptr<CKeybindManager> g_pKeybindManager;

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) {
@@ -121,8 +124,14 @@ void CHyprXWaylandManager::sendCloseWindow(CWindow* pWindow) {
void CHyprXWaylandManager::setWindowSize(CWindow* pWindow, const Vector2D& size) { void CHyprXWaylandManager::setWindowSize(CWindow* pWindow, const Vector2D& size) {
if (pWindow->m_bIsX11) if (pWindow->m_bIsX11)
wlr_xwayland_surface_configure(pWindow->m_uSurface.xwayland, pWindow->m_vRealPosition.vec().x, pWindow->m_vRealPosition.vec().y, size.x, size.y); wlr_xwayland_surface_configure(pWindow->m_uSurface.xwayland, pWindow->m_vRealPosition.vec().x, pWindow->m_vRealPosition.vec().y, size.x, size.y);
else // vvvvv I don't know if this is fucking correct, but the fucking idea of putting shadows into a window's surface is borderline criminal. else {
wlr_xdg_toplevel_set_size(pWindow->m_uSurface.xdg->toplevel, size.x - pWindow->m_uSurface.xdg->current.geometry.x * 2, size.y - pWindow->m_uSurface.xdg->current.geometry.y * 2); // I don't know if this is fucking correct, but the fucking idea of putting shadows into a window's surface is borderline criminal.
const auto XDELTA = pWindow->m_uSurface.xdg->current.geometry.width && pWindow->m_uSurface.xdg->current.geometry.height ? pWindow->m_uSurface.xdg->surface->current.width - pWindow->m_uSurface.xdg->current.geometry.width : 0;
const auto YDELTA = pWindow->m_uSurface.xdg->current.geometry.width && pWindow->m_uSurface.xdg->current.geometry.height ? pWindow->m_uSurface.xdg->surface->current.height - pWindow->m_uSurface.xdg->current.geometry.height : 0;
wlr_xdg_toplevel_set_size(pWindow->m_uSurface.xdg->toplevel, size.x - XDELTA, size.y - YDELTA);
}
} }
void CHyprXWaylandManager::setWindowStyleTiled(CWindow* pWindow, uint32_t edgez) { void CHyprXWaylandManager::setWindowStyleTiled(CWindow* pWindow, uint32_t edgez) {
@@ -217,5 +226,8 @@ void CHyprXWaylandManager::setWindowFullscreen(CWindow* pWindow, bool fullscreen
wlr_xdg_toplevel_set_fullscreen(pWindow->m_uSurface.xdg->toplevel, fullscreen); wlr_xdg_toplevel_set_fullscreen(pWindow->m_uSurface.xdg->toplevel, fullscreen);
} }
if (pWindow->m_phForeignToplevel)
wlr_foreign_toplevel_handle_v1_set_fullscreen(pWindow->m_phForeignToplevel, fullscreen);
g_pEventManager->postEvent(SHyprIPCEvent("fullscreen", std::to_string((int)fullscreen))); g_pEventManager->postEvent(SHyprIPCEvent("fullscreen", std::to_string((int)fullscreen)));
} }

View File

@@ -166,13 +166,17 @@ void CHyprOpenGLImpl::end() {
// end the render, copy the data to the WLR framebuffer // end the render, copy the data to the WLR framebuffer
if (!m_bFakeFrame) { if (!m_bFakeFrame) {
glBindFramebuffer(GL_FRAMEBUFFER, m_iWLROutputFb); glBindFramebuffer(GL_FRAMEBUFFER, m_iWLROutputFb);
wlr_box monbox = {0, 0, m_RenderData.pMonitor->vecPixelSize.x, m_RenderData.pMonitor->vecPixelSize.y}; wlr_box monbox = {0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y};
pixman_region32_copy(m_RenderData.pDamage, &m_rOriginalDamageRegion); pixman_region32_copy(m_RenderData.pDamage, &m_rOriginalDamageRegion);
clear(CColor(11, 11, 11, 255)); clear(CColor(11, 11, 11, 255));
m_bEndFrame = true;
renderTexture(m_mMonitorRenderResources[m_RenderData.pMonitor].primaryFB.m_cTex, &monbox, 255.f, 0); renderTexture(m_mMonitorRenderResources[m_RenderData.pMonitor].primaryFB.m_cTex, &monbox, 255.f, 0);
m_bEndFrame = false;
} }
// reset our data // reset our data
@@ -205,7 +209,15 @@ void CHyprOpenGLImpl::scissor(const wlr_box* pBox) {
return; return;
} }
glScissor(pBox->x, pBox->y, pBox->width, pBox->height); wlr_box newBox = *pBox;
int w, h;
wlr_output_transformed_resolution(m_RenderData.pMonitor->output, &w, &h);
const auto TR = wlr_output_transform_invert(m_RenderData.pMonitor->transform);
wlr_box_transform(&newBox, &newBox, TR, w, h);
glScissor(newBox.x, newBox.y, newBox.width, newBox.height);
glEnable(GL_SCISSOR_TEST); glEnable(GL_SCISSOR_TEST);
} }
@@ -217,8 +229,9 @@ void CHyprOpenGLImpl::scissor(const pixman_box32* pBox) {
return; return;
} }
glScissor(pBox->x1, pBox->y1, pBox->x2 - pBox->x1, pBox->y2 - pBox->y1); wlr_box newBox = {pBox->x1, pBox->y1, pBox->x2 - pBox->x1, pBox->y2 - pBox->y1};
glEnable(GL_SCISSOR_TEST);
scissor(&newBox);
} }
void CHyprOpenGLImpl::scissor(const int x, const int y, const int w, const int h) { void CHyprOpenGLImpl::scissor(const int x, const int y, const int w, const int h) {
@@ -231,7 +244,7 @@ void CHyprOpenGLImpl::renderRect(wlr_box* box, const CColor& col, int round) {
RASSERT(m_RenderData.pMonitor, "Tried to render rect without begin()!"); RASSERT(m_RenderData.pMonitor, "Tried to render rect without begin()!");
float matrix[9]; float matrix[9];
wlr_matrix_project_box(matrix, box, WL_OUTPUT_TRANSFORM_NORMAL, 0, m_RenderData.pMonitor->output->transform_matrix); // TODO: write own, don't use WLR here wlr_matrix_project_box(matrix, box, wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform), 0, m_RenderData.pMonitor->output->transform_matrix); // TODO: write own, don't use WLR here
float glMatrix[9]; float glMatrix[9];
wlr_matrix_multiply(glMatrix, m_RenderData.projection, matrix); wlr_matrix_multiply(glMatrix, m_RenderData.projection, matrix);
@@ -256,6 +269,7 @@ void CHyprOpenGLImpl::renderRect(wlr_box* box, const CColor& col, int round) {
glUniform2f(glGetUniformLocation(m_shQUAD.program, "bottomRight"), (float)BOTTOMRIGHT.x, (float)BOTTOMRIGHT.y); glUniform2f(glGetUniformLocation(m_shQUAD.program, "bottomRight"), (float)BOTTOMRIGHT.x, (float)BOTTOMRIGHT.y);
glUniform2f(glGetUniformLocation(m_shQUAD.program, "fullSize"), (float)FULLSIZE.x, (float)FULLSIZE.y); glUniform2f(glGetUniformLocation(m_shQUAD.program, "fullSize"), (float)FULLSIZE.x, (float)FULLSIZE.y);
glUniform1f(glGetUniformLocation(m_shQUAD.program, "radius"), round); glUniform1f(glGetUniformLocation(m_shQUAD.program, "radius"), round);
glUniform1i(glGetUniformLocation(m_shQUAD.program, "primitiveMultisample"), (int)(g_pConfigManager->getInt("decoration:multisample_edges") == 1 && round != 0));
glVertexAttribPointer(m_shQUAD.posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts); glVertexAttribPointer(m_shQUAD.posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
glVertexAttribPointer(m_shQUAD.texAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts); glVertexAttribPointer(m_shQUAD.texAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
@@ -291,12 +305,12 @@ void CHyprOpenGLImpl::renderTexture(const CTexture& tex, wlr_box* pBox, float al
scissor((wlr_box*)nullptr); scissor((wlr_box*)nullptr);
} }
void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_box* pBox, float alpha, pixman_region32_t* damage, int round, bool discardOpaque, bool border) { void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_box* pBox, float alpha, pixman_region32_t* damage, int round, bool discardOpaque, bool border, bool noAA) {
RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!"); RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!");
RASSERT((tex.m_iTexID > 0), "Attempted to draw NULL texture!"); RASSERT((tex.m_iTexID > 0), "Attempted to draw NULL texture!");
// get transform // get transform
const auto TRANSFORM = wlr_output_transform_invert(WL_OUTPUT_TRANSFORM_NORMAL); const auto TRANSFORM = wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform);
float matrix[9]; float matrix[9];
wlr_matrix_project_box(matrix, pBox, TRANSFORM, 0, m_RenderData.pMonitor->output->transform_matrix); wlr_matrix_project_box(matrix, pBox, TRANSFORM, 0, m_RenderData.pMonitor->output->transform_matrix);
@@ -349,6 +363,7 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_b
glUniform2f(glGetUniformLocation(shader->program, "bottomRight"), (float)BOTTOMRIGHT.x, (float)BOTTOMRIGHT.y); glUniform2f(glGetUniformLocation(shader->program, "bottomRight"), (float)BOTTOMRIGHT.x, (float)BOTTOMRIGHT.y);
glUniform2f(glGetUniformLocation(shader->program, "fullSize"), (float)FULLSIZE.x, (float)FULLSIZE.y); glUniform2f(glGetUniformLocation(shader->program, "fullSize"), (float)FULLSIZE.x, (float)FULLSIZE.y);
glUniform1f(glGetUniformLocation(shader->program, "radius"), round); glUniform1f(glGetUniformLocation(shader->program, "radius"), round);
glUniform1i(glGetUniformLocation(shader->program, "primitiveMultisample"), (int)(g_pConfigManager->getInt("decoration:multisample_edges") == 1 && round != 0 && !border && !noAA));
glVertexAttribPointer(shader->posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts); glVertexAttribPointer(shader->posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
glVertexAttribPointer(shader->texAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts); glVertexAttribPointer(shader->texAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
@@ -534,7 +549,7 @@ void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, wlr_box* pBox,
pixman_region32_t inverseOpaque; pixman_region32_t inverseOpaque;
pixman_region32_init(&inverseOpaque); pixman_region32_init(&inverseOpaque);
if (a == 255.f) { if (a == 255.f) {
pixman_box32_t monbox = {0, 0, m_RenderData.pMonitor->vecPixelSize.x, m_RenderData.pMonitor->vecPixelSize.y}; pixman_box32_t monbox = {0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y};
pixman_region32_copy(&inverseOpaque, &pSurface->current.opaque); pixman_region32_copy(&inverseOpaque, &pSurface->current.opaque);
pixman_region32_translate(&inverseOpaque, pBox->x, pBox->y); pixman_region32_translate(&inverseOpaque, pBox->x, pBox->y);
pixman_region32_inverse(&inverseOpaque, &inverseOpaque, &monbox); pixman_region32_inverse(&inverseOpaque, &inverseOpaque, &monbox);
@@ -572,11 +587,11 @@ void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, wlr_box* pBox,
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
// stencil done. Render everything. // stencil done. Render everything.
wlr_box MONITORBOX = {0, 0, m_RenderData.pMonitor->vecPixelSize.x, m_RenderData.pMonitor->vecPixelSize.y}; wlr_box MONITORBOX = {0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y};
if (pixman_region32_not_empty(&damage)) { if (pixman_region32_not_empty(&damage)) {
// render our great blurred FB // render our great blurred FB
renderTextureInternalWithDamage(POUTFB->m_cTex, &MONITORBOX, a, &damage); renderTextureInternalWithDamage(POUTFB->m_cTex, &MONITORBOX, g_pConfigManager->getInt("decoration:blur_ignore_opacity") ? 255.f : a, &damage);
// render the window, but clear stencil // render the window, but clear stencil
glClearStencil(0); glClearStencil(0);
glClear(GL_STENCIL_BUFFER_BIT); glClear(GL_STENCIL_BUFFER_BIT);
@@ -585,7 +600,7 @@ void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, wlr_box* pBox,
glStencilFunc(GL_ALWAYS, 1, -1); glStencilFunc(GL_ALWAYS, 1, -1);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
renderTextureInternalWithDamage(tex, pBox, a, &damage, round); renderTextureInternalWithDamage(tex, pBox, a, &damage, round, false, false, true);
// then stop // then stop
glStencilFunc(GL_EQUAL, 1, -1); glStencilFunc(GL_EQUAL, 1, -1);
@@ -624,7 +639,7 @@ void CHyprOpenGLImpl::renderBorder(wlr_box* box, const CColor& col, int thick, i
box->width += 2 * thick; box->width += 2 * thick;
box->height += 2 * thick; box->height += 2 * thick;
round += thick; // cuz yeah round += thick * m_RenderData.pMonitor->scale; // cuz yeah
// only draw on non-stencild. // only draw on non-stencild.
glStencilFunc(GL_NOTEQUAL, 1, -1); glStencilFunc(GL_NOTEQUAL, 1, -1);
@@ -756,7 +771,14 @@ void CHyprOpenGLImpl::renderSnapshot(CWindow** pWindow) {
const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID); const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID);
wlr_box windowBox = {0, 0, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y}; wlr_box windowBox;
// some mafs to figure out the correct box
Vector2D scaleXY = Vector2D((PWINDOW->m_vRealSize.vec().x / PWINDOW->m_vOriginalClosedSize.x), (PWINDOW->m_vRealSize.vec().y / PWINDOW->m_vOriginalClosedSize.y));
windowBox.width = PMONITOR->vecPixelSize.x * scaleXY.x;
windowBox.height = PMONITOR->vecPixelSize.y * scaleXY.y;
windowBox.x = (PWINDOW->m_vRealPosition.vec().x - PMONITOR->vecPosition.x) - ((PWINDOW->m_vOriginalClosedPos.x - PMONITOR->vecPosition.x) * scaleXY.x);
windowBox.y = (PWINDOW->m_vRealPosition.vec().y - PMONITOR->vecPosition.y) - ((PWINDOW->m_vOriginalClosedPos.y - PMONITOR->vecPosition.y) * scaleXY.y);
pixman_region32_t fakeDamage; pixman_region32_t fakeDamage;
pixman_region32_init_rect(&fakeDamage, 0, 0, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y); pixman_region32_init_rect(&fakeDamage, 0, 0, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y);
@@ -810,10 +832,10 @@ void CHyprOpenGLImpl::createBGTextureForMonitor(SMonitor* pMonitor) {
// get the adequate tex // get the adequate tex
std::string texPath = "/usr/share/hyprland/wall_"; std::string texPath = "/usr/share/hyprland/wall_";
Vector2D textureSize; Vector2D textureSize;
if (pMonitor->vecSize.x > 7000) { if (pMonitor->vecTransformedSize.x > 7000) {
textureSize = Vector2D(7680, 4320); textureSize = Vector2D(7680, 4320);
texPath += "8K.png"; texPath += "8K.png";
} else if (pMonitor->vecSize.x > 3000) { } else if (pMonitor->vecTransformedSize.x > 3000) {
textureSize = Vector2D(3840, 2160); textureSize = Vector2D(3840, 2160);
texPath += "4K.png"; texPath += "4K.png";
} else { } else {
@@ -846,7 +868,7 @@ void CHyprOpenGLImpl::createBGTextureForMonitor(SMonitor* pMonitor) {
void CHyprOpenGLImpl::clearWithTex() { void CHyprOpenGLImpl::clearWithTex() {
RASSERT(m_RenderData.pMonitor, "Tried to render BGtex without begin()!"); RASSERT(m_RenderData.pMonitor, "Tried to render BGtex without begin()!");
wlr_box box = {0, 0, m_RenderData.pMonitor->vecPixelSize.x, m_RenderData.pMonitor->vecPixelSize.y}; wlr_box box = {0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y};
renderTexture(m_mMonitorBGTextures[m_RenderData.pMonitor], &box, 255, 0); renderTexture(m_mMonitorBGTextures[m_RenderData.pMonitor], &box, 255, 0);
} }

View File

@@ -92,6 +92,7 @@ private:
std::string m_szExtensions; std::string m_szExtensions;
bool m_bFakeFrame = false; bool m_bFakeFrame = false;
bool m_bEndFrame = false;
// Shaders // Shaders
SQuad m_shQUAD; SQuad m_shQUAD;
@@ -109,7 +110,7 @@ private:
// returns the out FB, can be either Mirror or MirrorSwap // returns the out FB, can be either Mirror or MirrorSwap
CFramebuffer* blurMainFramebufferWithDamage(float a, wlr_box* pBox, pixman_region32_t* damage); CFramebuffer* blurMainFramebufferWithDamage(float a, wlr_box* pBox, pixman_region32_t* damage);
void renderTextureInternalWithDamage(const CTexture&, wlr_box* pBox, float a, pixman_region32_t* damage, int round = 0, bool discardOpaque = false, bool border = false); void renderTextureInternalWithDamage(const CTexture&, wlr_box* pBox, float a, pixman_region32_t* damage, int round = 0, bool discardOpaque = false, bool border = false, bool noAA = false);
void renderBorder(wlr_box*, const CColor&, int thick = 1, int round = 0); void renderBorder(wlr_box*, const CColor&, int thick = 1, int round = 0);
}; };

View File

@@ -19,18 +19,20 @@ void renderSurface(struct wlr_surface* surface, int x, int y, void* data) {
} }
scaleBox(&windowBox, RDATA->output->scale); scaleBox(&windowBox, RDATA->output->scale);
float rounding = RDATA->dontRound ? 0 : RDATA->rounding == -1 ? g_pConfigManager->getInt("decoration:rounding") : RDATA->rounding;
if (RDATA->surface && surface == RDATA->surface) if (RDATA->surface && surface == RDATA->surface)
g_pHyprOpenGL->renderTextureWithBlur(TEXTURE, &windowBox, RDATA->fadeAlpha * RDATA->alpha, surface, RDATA->dontRound ? 0 : g_pConfigManager->getInt("decoration:rounding"), RDATA->decorate); g_pHyprOpenGL->renderTextureWithBlur(TEXTURE, &windowBox, RDATA->fadeAlpha * RDATA->alpha, surface, rounding, RDATA->decorate);
else else
g_pHyprOpenGL->renderTexture(TEXTURE, &windowBox, RDATA->fadeAlpha * RDATA->alpha, RDATA->dontRound ? 0 : g_pConfigManager->getInt("decoration:rounding"), false, false); g_pHyprOpenGL->renderTexture(TEXTURE, &windowBox, RDATA->fadeAlpha * RDATA->alpha, rounding, false, false);
wlr_surface_send_frame_done(surface, RDATA->when); wlr_surface_send_frame_done(surface, RDATA->when);
wlr_presentation_surface_sampled_on_output(g_pCompositor->m_sWLRPresentation, surface, RDATA->output); wlr_presentation_surface_sampled_on_output(g_pCompositor->m_sWLRPresentation, surface, RDATA->output);
} }
bool shouldRenderWindow(CWindow* pWindow, SMonitor* pMonitor) { bool CHyprRenderer::shouldRenderWindow(CWindow* pWindow, SMonitor* pMonitor) {
wlr_box geometry = {pWindow->m_vRealPosition.vec().x, pWindow->m_vRealPosition.vec().y, pWindow->m_vRealSize.vec().x, pWindow->m_vRealSize.vec().y}; wlr_box geometry = pWindow->getFullWindowBoundingBox();
if (!wlr_output_layout_intersects(g_pCompositor->m_sWLROutputLayout, pMonitor->output, &geometry)) if (!wlr_output_layout_intersects(g_pCompositor->m_sWLROutputLayout, pMonitor->output, &geometry))
return false; return false;
@@ -44,6 +46,30 @@ bool shouldRenderWindow(CWindow* pWindow, SMonitor* pMonitor) {
if (g_pCompositor->isWorkspaceVisible(pWindow->m_iWorkspaceID) || (PWORKSPACE && PWORKSPACE->m_iMonitorID == pMonitor->ID && (PWORKSPACE->m_vRenderOffset.isBeingAnimated() || PWORKSPACE->m_fAlpha.isBeingAnimated()))) if (g_pCompositor->isWorkspaceVisible(pWindow->m_iWorkspaceID) || (PWORKSPACE && PWORKSPACE->m_iMonitorID == pMonitor->ID && (PWORKSPACE->m_vRenderOffset.isBeingAnimated() || PWORKSPACE->m_fAlpha.isBeingAnimated())))
return true; return true;
if (pMonitor->specialWorkspaceOpen && pWindow->m_iWorkspaceID == SPECIAL_WORKSPACE_ID)
return true;
return false;
}
bool CHyprRenderer::shouldRenderWindow(CWindow* pWindow) {
if (!g_pCompositor->windowValidMapped(pWindow))
return false;
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID);
if (g_pCompositor->isWorkspaceVisible(pWindow->m_iWorkspaceID))
return true;
for (auto& m : g_pCompositor->m_lMonitors) {
if (PWORKSPACE && PWORKSPACE->m_iMonitorID == m.ID && (PWORKSPACE->m_vRenderOffset.isBeingAnimated() || PWORKSPACE->m_fAlpha.isBeingAnimated()))
return true;
if (m.specialWorkspaceOpen && pWindow->m_iWorkspaceID == SPECIAL_WORKSPACE_ID)
return true;
}
return false; return false;
} }
@@ -55,7 +81,7 @@ void CHyprRenderer::renderWorkspaceWithFullscreenWindow(SMonitor* pMonitor, CWor
continue; continue;
// found it! // found it!
renderWindow(&w, pMonitor, time, false); renderWindow(&w, pMonitor, time, pWorkspace->m_efFullscreenMode != FULLSCREEN_FULL);
pWorkspaceWindow = &w; pWorkspaceWindow = &w;
} }
@@ -68,7 +94,29 @@ void CHyprRenderer::renderWorkspaceWithFullscreenWindow(SMonitor* pMonitor, CWor
renderWindow(&w, pMonitor, time, true); renderWindow(&w, pMonitor, time, true);
} }
// and then special windows
for (auto& w : g_pCompositor->m_lWindows) {
if (!g_pCompositor->windowValidMapped(&w) && !w.m_bFadingOut)
continue;
if (w.m_iWorkspaceID != SPECIAL_WORKSPACE_ID)
continue;
if (!shouldRenderWindow(&w, pMonitor))
continue;
// render the bad boy
renderWindow(&w, pMonitor, time, true);
}
// and the overlay layers // and the overlay layers
if (pWorkspace->m_efFullscreenMode != FULLSCREEN_FULL) {
// on non-full we draw the bar and shit
for (auto& ls : pMonitor->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_TOP]) {
renderLayer(ls, pMonitor, time);
}
}
for (auto& ls : pMonitor->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]) { for (auto& ls : pMonitor->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]) {
renderLayer(ls, pMonitor, time); renderLayer(ls, pMonitor, time);
} }
@@ -85,7 +133,8 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, SMonitor* pMonitor, timespec*
return; return;
if (pWindow->m_bFadingOut) { if (pWindow->m_bFadingOut) {
g_pHyprOpenGL->renderSnapshot(&pWindow); if (pMonitor->ID == pWindow->m_iMonitorID) // TODO: fix this
g_pHyprOpenGL->renderSnapshot(&pWindow);
return; return;
} }
@@ -95,16 +144,24 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, SMonitor* pMonitor, timespec*
renderdata.surface = g_pXWaylandManager->getWindowSurface(pWindow); renderdata.surface = g_pXWaylandManager->getWindowSurface(pWindow);
renderdata.w = std::clamp(pWindow->m_vRealSize.vec().x, (double)5, (double)1337420); // clamp the size to min 5, renderdata.w = std::clamp(pWindow->m_vRealSize.vec().x, (double)5, (double)1337420); // clamp the size to min 5,
renderdata.h = std::clamp(pWindow->m_vRealSize.vec().y, (double)5, (double)1337420); // otherwise we'll have issues later with invalid boxes renderdata.h = std::clamp(pWindow->m_vRealSize.vec().y, (double)5, (double)1337420); // otherwise we'll have issues later with invalid boxes
renderdata.dontRound = pWindow->m_bIsFullscreen; renderdata.dontRound = pWindow->m_bIsFullscreen && PWORKSPACE->m_efFullscreenMode == FULLSCREEN_FULL;
renderdata.fadeAlpha = pWindow->m_fAlpha.fl() * (PWORKSPACE->m_fAlpha.fl() / 255.f); renderdata.fadeAlpha = pWindow->m_fAlpha.fl() * (PWORKSPACE->m_fAlpha.fl() / 255.f);
renderdata.alpha = pWindow->m_bIsFullscreen ? g_pConfigManager->getFloat("decoration:fullscreen_opacity") : pWindow == g_pCompositor->m_pLastWindow ? g_pConfigManager->getFloat("decoration:active_opacity") : g_pConfigManager->getFloat("decoration:inactive_opacity"); renderdata.alpha = pWindow->m_bIsFullscreen ? g_pConfigManager->getFloat("decoration:fullscreen_opacity") : pWindow == g_pCompositor->m_pLastWindow ? g_pConfigManager->getFloat("decoration:active_opacity") : g_pConfigManager->getFloat("decoration:inactive_opacity");
renderdata.decorate = decorate && !pWindow->m_bX11DoesntWantBorders; renderdata.decorate = decorate && !pWindow->m_bX11DoesntWantBorders;
renderdata.rounding = pWindow->m_sAdditionalConfigData.rounding;
// apply window special data // apply window special data
renderdata.alpha *= pWindow->m_sSpecialRenderData.alpha; if (pWindow->m_sSpecialRenderData.alphaInactive == -1)
renderdata.alpha *= pWindow->m_sSpecialRenderData.alpha;
else
renderdata.alpha *= pWindow == g_pCompositor->m_pLastWindow ? pWindow->m_sSpecialRenderData.alpha : pWindow->m_sSpecialRenderData.alphaInactive;
g_pHyprOpenGL->m_pCurrentWindow = pWindow; g_pHyprOpenGL->m_pCurrentWindow = pWindow;
// render window decorations first
for (auto& wd : pWindow->m_dWindowDecorations)
wd->draw(pMonitor);
wlr_surface_for_each_surface(g_pXWaylandManager->getWindowSurface(pWindow), renderSurface, &renderdata); wlr_surface_for_each_surface(g_pXWaylandManager->getWindowSurface(pWindow), renderSurface, &renderdata);
if (pWindow->m_bIsX11) { if (pWindow->m_bIsX11) {
@@ -161,7 +218,10 @@ void CHyprRenderer::renderAllClientsForMonitor(const int& ID, timespec* time) {
continue; continue;
if (w.m_bIsFloating) if (w.m_bIsFloating)
continue; // floating are in second pass continue; // floating are in the second pass
if (w.m_iWorkspaceID == SPECIAL_WORKSPACE_ID)
continue; // special are in the third pass
if (!shouldRenderWindow(&w, PMONITOR)) if (!shouldRenderWindow(&w, PMONITOR))
continue; continue;
@@ -178,6 +238,24 @@ void CHyprRenderer::renderAllClientsForMonitor(const int& ID, timespec* time) {
if (!w.m_bIsFloating) if (!w.m_bIsFloating)
continue; continue;
if (w.m_iWorkspaceID == SPECIAL_WORKSPACE_ID)
continue;
if (!shouldRenderWindow(&w, PMONITOR))
continue;
// render the bad boy
renderWindow(&w, PMONITOR, time, true);
}
// and then special
for (auto& w : g_pCompositor->m_lWindows) {
if (!g_pCompositor->windowValidMapped(&w) && !w.m_bFadingOut)
continue;
if (w.m_iWorkspaceID != SPECIAL_WORKSPACE_ID)
continue;
if (!shouldRenderWindow(&w, PMONITOR)) if (!shouldRenderWindow(&w, PMONITOR))
continue; continue;
@@ -194,10 +272,6 @@ void CHyprRenderer::renderAllClientsForMonitor(const int& ID, timespec* time) {
} }
renderDragIcon(PMONITOR, time); renderDragIcon(PMONITOR, time);
// if correct monitor draw hyprerror
if (PMONITOR == &g_pCompositor->m_lMonitors.front())
g_pHyprError->draw();
} }
void CHyprRenderer::outputMgrApplyTest(wlr_output_configuration_v1* config, bool test) { void CHyprRenderer::outputMgrApplyTest(wlr_output_configuration_v1* config, bool test) {
@@ -548,7 +622,7 @@ void CHyprRenderer::applyMonitorRule(SMonitor* pMonitor, SMonitorRule* pMonitorR
Debug::log(LOG, "Applying monitor rule for %s", pMonitor->szName.c_str()); Debug::log(LOG, "Applying monitor rule for %s", pMonitor->szName.c_str());
// Check if the rule isn't already applied // Check if the rule isn't already applied
if (!force && DELTALESSTHAN(pMonitor->vecPixelSize.x, pMonitorRule->resolution.x, 1) && DELTALESSTHAN(pMonitor->vecPixelSize.y, pMonitorRule->resolution.y, 1) && DELTALESSTHAN(pMonitor->refreshRate, pMonitorRule->refreshRate, 1) && pMonitor->scale == pMonitorRule->scale && DELTALESSTHAN(pMonitor->vecPosition.x, pMonitorRule->offset.x, 1) && DELTALESSTHAN(pMonitor->vecPosition.y, pMonitorRule->offset.y, 1)) { if (!force && DELTALESSTHAN(pMonitor->vecPixelSize.x, pMonitorRule->resolution.x, 1) && DELTALESSTHAN(pMonitor->vecPixelSize.y, pMonitorRule->resolution.y, 1) && DELTALESSTHAN(pMonitor->refreshRate, pMonitorRule->refreshRate, 1) && pMonitor->scale == pMonitorRule->scale && DELTALESSTHAN(pMonitor->vecPosition.x, pMonitorRule->offset.x, 1) && DELTALESSTHAN(pMonitor->vecPosition.y, pMonitorRule->offset.y, 1) && pMonitor->transform == pMonitorRule->transform) {
Debug::log(LOG, "Not applying a new rule to %s because it's already applied!", pMonitor->szName.c_str()); Debug::log(LOG, "Not applying a new rule to %s because it's already applied!", pMonitor->szName.c_str());
return; return;
} }
@@ -612,8 +686,10 @@ void CHyprRenderer::applyMonitorRule(SMonitor* pMonitor, SMonitorRule* pMonitorR
pMonitor->vecSize = pMonitorRule->resolution; pMonitor->vecSize = pMonitorRule->resolution;
} }
wlr_output_set_transform(pMonitor->output, pMonitorRule->transform);
pMonitor->transform = pMonitorRule->transform;
pMonitor->vecPixelSize = pMonitor->vecSize; pMonitor->vecPixelSize = pMonitor->vecSize;
pMonitor->vecSize = (pMonitor->vecSize / pMonitor->scale).floor();
// update renderer // update renderer
g_pHyprOpenGL->destroyMonitorResources(pMonitor); g_pHyprOpenGL->destroyMonitorResources(pMonitor);
@@ -623,6 +699,11 @@ void CHyprRenderer::applyMonitorRule(SMonitor* pMonitor, SMonitorRule* pMonitorR
return; return;
} }
int x, y;
wlr_output_transformed_resolution(pMonitor->output, &x, &y);
pMonitor->vecSize = (Vector2D(x, y) / pMonitor->scale).floor();
pMonitor->vecTransformedSize = Vector2D(x,y);
wlr_output_layout_add(g_pCompositor->m_sWLROutputLayout, pMonitor->output, (int)pMonitorRule->offset.x, (int)pMonitorRule->offset.y); wlr_output_layout_add(g_pCompositor->m_sWLROutputLayout, pMonitor->output, (int)pMonitorRule->offset.x, (int)pMonitorRule->offset.y);
//wlr_output_damage_add_whole(pMonitor->damage); //wlr_output_damage_add_whole(pMonitor->damage);
@@ -636,5 +717,5 @@ void CHyprRenderer::applyMonitorRule(SMonitor* pMonitor, SMonitorRule* pMonitorR
arrangeLayersForMonitor(pMonitor->ID); arrangeLayersForMonitor(pMonitor->ID);
// frame skip // frame skip
pMonitor->needsFrameSkip = true; pMonitor->framesToSkip = 1;
} }

View File

@@ -29,6 +29,8 @@ public:
void damageBox(const int& x, const int& y, const int& w, const int& h); void damageBox(const int& x, const int& y, const int& w, const int& h);
void damageMonitor(SMonitor*); void damageMonitor(SMonitor*);
void applyMonitorRule(SMonitor*, SMonitorRule*, bool force = false); void applyMonitorRule(SMonitor*, SMonitorRule*, bool force = false);
bool shouldRenderWindow(CWindow*, SMonitor*);
bool shouldRenderWindow(CWindow*);
DAMAGETRACKINGMODES damageTrackingModeFromStr(const std::string&); DAMAGETRACKINGMODES damageTrackingModeFromStr(const std::string&);

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

View File

@@ -0,0 +1,95 @@
#include "CHyprGroupBarDecoration.hpp"
#include "../../Compositor.hpp"
CHyprGroupBarDecoration::CHyprGroupBarDecoration(CWindow* pWindow) {
m_pWindow = pWindow;
updateWindow(pWindow);
}
CHyprGroupBarDecoration::~CHyprGroupBarDecoration() {
}
SWindowDecorationExtents CHyprGroupBarDecoration::getWindowDecorationExtents() {
return m_seExtents;
}
eDecorationType CHyprGroupBarDecoration::getDecorationType() {
return DECORATION_GROUPBAR;
}
void CHyprGroupBarDecoration::updateWindow(CWindow* pWindow) {
damageEntire();
if (pWindow->m_vRealPosition.vec() != m_vLastWindowPos || pWindow->m_vRealSize.vec() != m_vLastWindowSize) {
// we draw 3px above the window's border with 3px
const auto BORDERSIZE = g_pConfigManager->getInt("general:border_size");
m_seExtents.topLeft = Vector2D(0, BORDERSIZE + 3 + 3);
m_seExtents.bottomRight = Vector2D();
m_vLastWindowPos = pWindow->m_vRealPosition.vec();
m_vLastWindowSize = pWindow->m_vRealSize.vec();
}
// let's check if the window group is different.
if (g_pLayoutManager->getCurrentLayout()->getLayoutName() != "dwindle") {
// ????
for (auto it = pWindow->m_dWindowDecorations.begin(); it != pWindow->m_dWindowDecorations.end(); it++) {
if (it->get() == this) {
pWindow->m_dWindowDecorations.erase(it);
return;
}
}
}
// get the group info
SLayoutMessageHeader header;
header.pWindow = g_pCompositor->m_pLastWindow;
m_dwGroupMembers = std::any_cast<std::deque<CWindow*>>(g_pLayoutManager->getCurrentLayout()->layoutMessage(header, "groupinfo"));
damageEntire();
if (m_dwGroupMembers.size() == 0) {
// remove
for (auto it = pWindow->m_dWindowDecorations.begin(); it != pWindow->m_dWindowDecorations.end(); it++) {
if (it->get() == this) {
pWindow->m_dWindowDecorations.erase(it);
return;
}
}
}
}
void CHyprGroupBarDecoration::damageEntire() {
wlr_box dm = {m_vLastWindowPos.x - m_seExtents.topLeft.x, m_vLastWindowPos.y - m_seExtents.topLeft.y, m_vLastWindowSize.x + m_seExtents.topLeft.x + m_seExtents.bottomRight.x, m_seExtents.topLeft.y};
g_pHyprRenderer->damageBox(&dm);
}
void CHyprGroupBarDecoration::draw(SMonitor* pMonitor) {
// get how many bars we will draw
int barsToDraw = m_dwGroupMembers.size();
if (barsToDraw < 1 || m_pWindow->m_bHidden || !g_pCompositor->windowValidMapped(m_pWindow))
return;
const int PAD = 2; //2px
const int BARW = (m_vLastWindowSize.x - PAD * (barsToDraw - 1)) / barsToDraw;
int xoff = 0;
for (int i = 0; i < barsToDraw; ++i) {
wlr_box rect = {m_vLastWindowPos.x + xoff - pMonitor->vecPosition.x, m_vLastWindowPos.y - m_seExtents.topLeft.y - pMonitor->vecPosition.y, BARW, 3};
if (rect.width <= 0 || rect.height <= 0)
break;
CColor color = m_dwGroupMembers[i] == g_pCompositor->m_pLastWindow ? CColor(g_pConfigManager->getInt("dwindle:col.group_border_active")) : CColor(g_pConfigManager->getInt("dwindle:col.group_border"));
g_pHyprOpenGL->renderRect(&rect, color);
xoff += PAD + BARW;
}
}

View File

@@ -0,0 +1,30 @@
#pragma once
#include "IHyprWindowDecoration.hpp"
#include <deque>
class CHyprGroupBarDecoration : public IHyprWindowDecoration {
public:
CHyprGroupBarDecoration(CWindow*);
virtual ~CHyprGroupBarDecoration();
virtual SWindowDecorationExtents getWindowDecorationExtents();
virtual void draw(SMonitor*);
virtual eDecorationType getDecorationType();
virtual void updateWindow(CWindow*);
virtual void damageEntire();
private:
SWindowDecorationExtents m_seExtents;
CWindow* m_pWindow = nullptr;
Vector2D m_vLastWindowPos;
Vector2D m_vLastWindowSize;
std::deque<CWindow*> m_dwGroupMembers;
};

View File

@@ -0,0 +1,7 @@
#include "IHyprWindowDecoration.hpp"
#include "../../Window.hpp"
IHyprWindowDecoration::~IHyprWindowDecoration() {
}

View File

@@ -0,0 +1,31 @@
#pragma once
#include "../../defines.hpp"
enum eDecorationType {
DECORATION_NONE = -1,
DECORATION_GROUPBAR
};
struct SWindowDecorationExtents {
Vector2D topLeft;
Vector2D bottomRight;
};
class CWindow;
struct SMonitor;
class IHyprWindowDecoration {
public:
virtual ~IHyprWindowDecoration() = 0;
virtual SWindowDecorationExtents getWindowDecorationExtents() = 0;
virtual void draw(SMonitor*) = 0;
virtual eDecorationType getDecorationType() = 0;
virtual void updateWindow(CWindow*) = 0;
virtual void damageEntire() = 0;
};

1
wlroots Submodule

Submodule wlroots added at 75d31509db