Compare commits
515 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
4520b30d49 | ||
|
8405aa111d | ||
|
ad46257cce | ||
|
0cfbe618b5 | ||
|
7d0944acdf | ||
|
b9990468f3 | ||
|
736a8735b3 | ||
|
b54eecbd79 | ||
|
657aeb3946 | ||
|
6807430b18 | ||
|
0c7a7e2d56 | ||
|
0ec6072a29 | ||
|
3ca699debf | ||
|
52c0919621 | ||
|
6fbfeefc71 | ||
|
46bf87c8d1 | ||
|
595eb89f6e | ||
|
a815b14bf1 | ||
|
3a5052a714 | ||
|
8e237b006f | ||
|
1ed925b69c | ||
|
aed529f695 | ||
|
de68e065fe | ||
|
e2426942e5 | ||
|
5c6c300abf | ||
|
6bd3397141 | ||
|
68fd32c810 | ||
|
3ddb16bd5b | ||
|
f6387536f6 | ||
|
968f6a6013 | ||
|
488efab636 | ||
|
6649255d54 | ||
|
4b00cba319 | ||
|
9e418671e1 | ||
|
d73c14751a | ||
|
6f313de952 | ||
|
2cf6e7862a | ||
|
58669fef77 | ||
|
e20aef7d53 | ||
|
b2143a98e2 | ||
|
f75f8efb1b | ||
|
be96787ed0 | ||
|
89d945aabe | ||
|
27211c71e9 | ||
|
14942bca60 | ||
|
77f2a01304 | ||
|
7b56ce6521 | ||
|
32a8caf7e7 | ||
|
caaa9b11e4 | ||
|
b1ad2d8066 | ||
|
22746b3046 | ||
|
49713fab04 | ||
|
8b86ee8bf0 | ||
|
2a052c69f3 | ||
|
2320b2241c | ||
|
8f5188269b | ||
|
00c8626863 | ||
|
0a211f29f5 | ||
|
d279d7c4c6 | ||
|
6c78b03bb7 | ||
|
f79497087b | ||
|
508bde1f61 | ||
|
e5ff19ac0f | ||
|
8579066c7a | ||
|
9232bc2c00 | ||
|
db0b764a5a | ||
|
278583b8a1 | ||
|
4414cd07e2 | ||
|
9e98fb0167 | ||
|
9856378384 | ||
|
dfa1bd0cd4 | ||
|
92df6b0dce | ||
|
71963972bf | ||
|
1bc05b1f9f | ||
|
e6cf643f5a | ||
|
94140e886e | ||
|
b248d59713 | ||
|
cbc0ff6ec0 | ||
|
6b6554adb8 | ||
|
d936eb437b | ||
|
883d01084c | ||
|
0564b46a5e | ||
|
3c9716acfd | ||
|
581f6659f8 | ||
|
e72ae6b25f | ||
|
9e35656244 | ||
|
e87758529e | ||
|
eb97d949aa | ||
|
e74efd87e5 | ||
|
4dbdb556fe | ||
|
5ee4b19691 | ||
|
d35e70a8c6 | ||
|
c35ed8363f | ||
|
d505b33665 | ||
|
118be4dea0 | ||
|
73b9756b8d | ||
|
8b9e385943 | ||
|
e01da1fd7a | ||
|
7a8c013edc | ||
|
518399a95b | ||
|
155d44016d | ||
|
13f90bb87a | ||
|
c67b257e51 | ||
|
8237d7e1a4 | ||
|
85da1a17d8 | ||
|
9609b04ff9 | ||
|
04421063af | ||
|
43e1415e71 | ||
|
e1448732b3 | ||
|
7c4c402bd7 | ||
|
6179b17903 | ||
|
05b48d48d9 | ||
|
07a21fdfa9 | ||
|
0f594732b0 | ||
|
312411fc70 | ||
|
70add904c4 | ||
|
5ca4823128 | ||
|
0500213086 | ||
|
b0fca6eaf0 | ||
|
4988e00b1d | ||
|
0fad7a0bb0 | ||
|
727f1b54cd | ||
|
c80457be02 | ||
|
4a42c5ed20 | ||
|
bd6d6e7f33 | ||
|
027140b731 | ||
|
ea10592ad3 | ||
|
9b54342baa | ||
|
8f9887b0c9 | ||
|
fa39df4731 | ||
|
f7249bd331 | ||
|
6934e7aa2b | ||
|
8bbeee2041 | ||
|
7a24e564f4 | ||
|
4b5b8a7630 | ||
|
5b1375141b | ||
|
4af9410dc2 | ||
|
a6315b0af4 | ||
|
cac59fefec | ||
|
1ac2fc3f7e | ||
|
cf6a1716ae | ||
|
10d7219807 | ||
|
838ed87d6f | ||
|
76b82fdde7 | ||
|
c5fd577181 | ||
|
fbd6354393 | ||
|
fd8d8e122e | ||
|
1c9d56998d | ||
|
242e06b242 | ||
|
25e72949a1 | ||
|
259dcd838e | ||
|
ef33198e8f | ||
|
604eb21a7e | ||
|
92a0dd164e | ||
|
b9b8e6220f | ||
|
a95df6b57e | ||
|
9642311ac2 | ||
|
98e99cd03d | ||
|
8210a1d7ac | ||
|
d105c7403c | ||
|
00ee1cf98e | ||
|
7dd0f76e5a | ||
|
17ed4fc04c | ||
|
6a8824253c | ||
|
eb42adc4c0 | ||
|
09dbcabcc7 | ||
|
72c7818ae6 | ||
|
1ea47950f4 | ||
|
8d6c18076f | ||
|
9c5a37a797 | ||
|
ca85455a8e | ||
|
28f6c2df59 | ||
|
83ab3ae0af | ||
|
b672118f92 | ||
|
aac90d9279 | ||
|
66586c38f5 | ||
|
82c67e61a9 | ||
|
e45e606fbd | ||
|
688fe5c147 | ||
|
a3b75559b3 | ||
|
df4f222482 | ||
|
3b663f4afc | ||
|
f634b9e61a | ||
|
bdb296a83c | ||
|
4fa63104c9 | ||
|
a437e44a6a | ||
|
cae937c51b | ||
|
8162fae377 | ||
|
c5786be695 | ||
|
1b1ecf77e0 | ||
|
883463f9dd | ||
|
3e7325af57 | ||
|
946ed1f32a | ||
|
4eff224a7f | ||
|
c86db7bbb0 | ||
|
272d904870 | ||
|
01e3da4d51 | ||
|
33015546c6 | ||
|
83d88fa564 | ||
|
11dfb8397b | ||
|
f4045ab8d0 | ||
|
fa12efdd2a | ||
|
bf611fbbf3 | ||
|
5afc4dc42e | ||
|
50348a3ddb | ||
|
279ec1c291 | ||
|
1006663b6e | ||
|
b2a18aa80a | ||
|
d21a6b12b8 | ||
|
912e7ba82d | ||
|
92744b5b9a | ||
|
c5feee1e35 | ||
|
1840a907a8 | ||
|
682b30fba8 | ||
|
12d9901472 | ||
|
15f942000e | ||
|
520e91238f | ||
|
0c56be74a3 | ||
|
069faa4027 | ||
|
c30dfe92ee | ||
|
d85ae306c5 | ||
|
197f880790 | ||
|
3b4aabe04c | ||
|
c5ec079c6f | ||
|
4aec237ec0 | ||
|
39df1f4dbf | ||
|
77cf651825 | ||
|
c7b72790bd | ||
|
3fa6db1e7a | ||
|
d361fcbd85 | ||
|
df9d830117 | ||
|
118d4e1001 | ||
|
511eea71c6 | ||
|
01ff5fdf6a | ||
|
0bf9ceb53b | ||
|
4fdc0d55e4 | ||
|
8b37e81374 | ||
|
fd1d4e288e | ||
|
4b4971c06f | ||
|
83a334f97d | ||
|
9a09eac79b | ||
|
2d552fbaa2 | ||
|
ea72831541 | ||
|
a399f98c68 | ||
|
3e00d7dde7 | ||
|
d5bc3eb1fa | ||
|
99e9cb5107 | ||
|
f36c625e37 | ||
|
2e3dc17a7e | ||
|
b2717cf7fd | ||
|
3d82d199f0 | ||
|
a05da63d85 | ||
|
5b736a4a66 | ||
|
fa6ee51367 | ||
|
b0a70f63e3 | ||
|
d597ae41b9 | ||
|
640d161851 | ||
|
0e86808e59 | ||
|
2b520571e8 | ||
|
5dd2c27b63 | ||
|
4ae89e1f22 | ||
|
51ffd7fa6f | ||
|
ae50f8614d | ||
|
9f5a57ff45 | ||
|
4141e67550 | ||
|
be2dfa36ef | ||
|
1fa4b7d79b | ||
|
592b4a709c | ||
|
09bb5658b7 | ||
|
ab0a3268e0 | ||
|
c8873b958d | ||
|
60571cd5cc | ||
|
5edfa627b4 | ||
|
95959789b7 | ||
|
8c02b3c267 | ||
|
5b7057c479 | ||
|
37e1411e8d | ||
|
5489682799 | ||
|
e989a0bcff | ||
|
8a5f9bbb39 | ||
|
3b9b5346b8 | ||
|
8ec3dc4c09 | ||
|
cc7c117fe7 | ||
|
1c221240d0 | ||
|
c1afc82a4c | ||
|
f3a9f9ec45 | ||
|
10e631053a | ||
|
46c6efeab3 | ||
|
68ee4dda5e | ||
|
743e98f0c0 | ||
|
e673220340 | ||
|
9c38b0fdbe | ||
|
60b663e276 | ||
|
01560c9d7c | ||
|
3a1afb53fd | ||
|
23a8f06594 | ||
|
70468857da | ||
|
87699575e1 | ||
|
33e513d489 | ||
|
6e6c61b9e8 | ||
|
a9d87bd666 | ||
|
7df9b01d48 | ||
|
256db08aed | ||
|
73d09953e8 | ||
|
fcff2dcac2 | ||
|
3cc2028def | ||
|
9b6ae4f77b | ||
|
bc86afea7e | ||
|
6edfdd63a1 | ||
|
04b40ea2ec | ||
|
55ceca4cdd | ||
|
10e8af00d6 | ||
|
ad711ef421 | ||
|
ae638d997d | ||
|
141cd09bd3 | ||
|
0243271544 | ||
|
729b47d46d | ||
|
84227eb587 | ||
|
daed75219f | ||
|
ec672b1ab9 | ||
|
963816b9a6 | ||
|
534fdb5a37 | ||
|
682865632f | ||
|
76610d9fb0 | ||
|
57371b93a0 | ||
|
33a5c8ce32 | ||
|
a0d15a0b7b | ||
|
cd942ad12d | ||
|
daf5fad190 | ||
|
4beac91cbd | ||
|
391f1ae838 | ||
|
381cb2d833 | ||
|
a0be3de0e8 | ||
|
3e543d2ce8 | ||
|
735e3c6c56 | ||
|
b16fb9770c | ||
|
f2b6ebbf54 | ||
|
fe19754887 | ||
|
72bce7efd5 | ||
|
99088eaed8 | ||
|
2da3cfb422 | ||
|
e2efecc24e | ||
|
8a4548e430 | ||
|
a5f58a3126 | ||
|
077494ee85 | ||
|
752604cfe9 | ||
|
3c758db95c | ||
|
7c68236a51 | ||
|
4c3b035162 | ||
|
f17f8b219c | ||
|
e8374e0792 | ||
|
77b134e23b | ||
|
87db950189 | ||
|
5bae7f150b | ||
|
83a5395eaa | ||
|
d03fa94c2c | ||
|
511e9ccdd1 | ||
|
3132f0275e | ||
|
1797319a07 | ||
|
5979ceb56b | ||
|
672bf1f867 | ||
|
33e933e2a0 | ||
|
341fb4497f | ||
|
cbaac6deaf | ||
|
3b6bcd6ddc | ||
|
e6fc9873b5 | ||
|
db1f5cd137 | ||
|
928d1dd38a | ||
|
faa157e162 | ||
|
7f624d2236 | ||
|
f7fb7e7e49 | ||
|
efcbcd7297 | ||
|
043b859ea2 | ||
|
cf373d315e | ||
|
016da234d0 | ||
|
f642fb97df | ||
|
9b0993cc49 | ||
|
efccf25fcc | ||
|
8e15f91c24 | ||
|
300228b503 | ||
|
293e687389 | ||
|
da956c8a97 | ||
|
bd526822de | ||
|
f442f435d3 | ||
|
bc6b0880dd | ||
|
ed6c701144 | ||
|
45c4898423 | ||
|
a770a88e09 | ||
|
1f64668953 | ||
|
13bc7e1e14 | ||
|
7486576fa7 | ||
|
f85c6416c6 | ||
|
e728e56cbc | ||
|
9ff83f4aa9 | ||
|
3247d18a7c | ||
|
a443902abc | ||
|
b03f41efec | ||
|
648f824b9e | ||
|
22138ac259 | ||
|
19fb13e6cf | ||
|
ede1e63f69 | ||
|
cc98594c3a | ||
|
0502c3f62b | ||
|
0a6e83005f | ||
|
e894d5e964 | ||
|
8bb75a223d | ||
|
6247a6b537 | ||
|
2fa57f2dc4 | ||
|
e58fd3bfb0 | ||
|
d7ea1b7785 | ||
|
4d6f96f74f | ||
|
8ff9410d2c | ||
|
718afe271e | ||
|
1f43a5c859 | ||
|
9c5dd59d4b | ||
|
d16c6aa1db | ||
|
ac11771348 | ||
|
f2dc48d92f | ||
|
e4d09aa3a9 | ||
|
c338acbb7d | ||
|
95782de966 | ||
|
3ba3d20ad3 | ||
|
1d70962892 | ||
|
918d8340af | ||
|
4f7113972e | ||
|
8121e66f34 | ||
|
784c0b5ccb | ||
|
eef207ce0a | ||
|
4dd2b5902e | ||
|
cff0123ce6 | ||
|
8a68199a0c | ||
|
e09addf8de | ||
|
315f16d501 | ||
|
7f09646ab8 | ||
|
0b924f541c | ||
|
4778afe2e6 | ||
|
fa022901cf | ||
|
4a8b13ea4f | ||
|
8cf2ca1966 | ||
|
fabc30df52 | ||
|
d6de248b0d | ||
|
c1e21719a2 | ||
|
def5fcb212 | ||
|
65f04f265c | ||
|
6d21014a50 | ||
|
20a465f69d | ||
|
fb15b7aa2a | ||
|
6e5804b53d | ||
|
e0e3c4c6ae | ||
|
b98e0876d3 | ||
|
236150b3c5 | ||
|
d1340bd1d8 | ||
|
28ce0e0f80 | ||
|
a9c7a0830f | ||
|
785d062887 | ||
|
1360677478 | ||
|
14ab0ecc5e | ||
|
9cb3bf1cac | ||
|
b15be9c77d | ||
|
d5ef10abf4 | ||
|
172ee1cada | ||
|
738530e62e | ||
|
069a21a34e | ||
|
2031af82fa | ||
|
d0a6fa7aa6 | ||
|
648ac8a00b | ||
|
43c75f17eb | ||
|
1b5444494d | ||
|
3eaf35f1e2 | ||
|
2566d81884 | ||
|
1f5fd7e64a | ||
|
908bec1564 | ||
|
89f795da98 | ||
|
91fe58f8f2 | ||
|
77f44bfcab | ||
|
6c24dc0bb1 | ||
|
46ef6653be | ||
|
fb82f6bcd7 | ||
|
32aca88752 | ||
|
df0c014ba0 | ||
|
cb63398f07 | ||
|
2f278dc883 | ||
|
12ce06f39b | ||
|
a357fa3e0a | ||
|
a9d53a2252 | ||
|
b2590b58c5 | ||
|
9cd5b3587c | ||
|
8055b1c00a | ||
|
5de273a144 | ||
|
4842eb83b4 | ||
|
e6d10539af | ||
|
9e781040d9 | ||
|
a54f98c203 | ||
|
d677ac6f87 | ||
|
a9d7befc36 | ||
|
0e18da8467 | ||
|
18ee9ece9c | ||
|
38132ffaf5 | ||
|
a99f314106 | ||
|
9d7d5ec3c8 | ||
|
c7e85e26f7 | ||
|
1bae19ce85 | ||
|
f687105eff | ||
|
32283ed706 | ||
|
8412ffcc42 | ||
|
b6bf4afb48 | ||
|
e1b05f8eaf | ||
|
21b9e31bf4 | ||
|
1c388e52fb | ||
|
8c64a4bad7 | ||
|
1f46296ea0 | ||
|
809820921d | ||
|
90d0097716 | ||
|
b17381eb81 | ||
|
811429bfd4 |
30
.github/ISSUE_TEMPLATE/bug.yml
vendored
@@ -2,21 +2,25 @@ name: Bug Report
|
||||
description: Something is not working right
|
||||
labels: ["bug"]
|
||||
body:
|
||||
- type: markdown
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
value: |
|
||||
Before opening a new issue, take a moment to search through the current open ones.
|
||||
|
||||
---
|
||||
label: Already reported ? *
|
||||
description: Before opening a new bug report, please take a moment to search through the current open and closed issues to check if it already exists.
|
||||
options:
|
||||
- label: I have searched the existing open and closed issues.
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
id: type
|
||||
attributes:
|
||||
label: Bug or Regression?
|
||||
description: Is this a bug or a regression?
|
||||
label: Regression?
|
||||
description: |
|
||||
Regression means that something used to work but no longer does.
|
||||
**BEFORE CONTINUING**, please check if this bug is a regression or not, and if it is, we need you to bisect with the help of the wiki: https://wiki.hyprland.org/Crashes-and-Bugs/#bisecting-an-issue
|
||||
multiple: true
|
||||
options:
|
||||
- Bug
|
||||
- Regression
|
||||
- "Yes"
|
||||
- "No"
|
||||
validations:
|
||||
required: true
|
||||
|
||||
@@ -25,10 +29,10 @@ body:
|
||||
attributes:
|
||||
label: System Info and Version
|
||||
description: |
|
||||
Paste the output of `hyprctl systeminfo -c` here (If you are on a
|
||||
version that shows you help menu, omit the `-c` and attach config files
|
||||
to the issue). If you have configs outside of the main config shown
|
||||
here, please attach.
|
||||
Paste the output of `hyprctl systeminfo -c` here. If you can't
|
||||
launch Hyprland, paste the output of `Hyprland --systeminfo`.
|
||||
If `Hyprland --systeminfo` errors out (added in 0.44.0), find
|
||||
and paste the Hyprland version manually.
|
||||
value: "<details>
|
||||
<summary>System/Version info</summary>
|
||||
|
||||
|
11
.github/actions/setup_base/action.yml
vendored
@@ -34,6 +34,7 @@ runs:
|
||||
libglvnd \
|
||||
libinput \
|
||||
libliftoff \
|
||||
libxcursor \
|
||||
libxcvt \
|
||||
libxfont2 \
|
||||
libxkbcommon \
|
||||
@@ -68,6 +69,16 @@ runs:
|
||||
cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
|
||||
cmake --install build
|
||||
|
||||
- name: Get hyprutils-git
|
||||
shell: bash
|
||||
run: |
|
||||
git clone https://github.com/hyprwm/hyprutils && cd hyprutils && cmake -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:PATH=/usr -B build && cmake --build build --target hyprutils && cmake --install build
|
||||
|
||||
- name: Get aquamarine-git
|
||||
shell: bash
|
||||
run: |
|
||||
git clone https://github.com/hyprwm/aquamarine && cd aquamarine && cmake -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:PATH=/usr -B build && cmake --build build --target aquamarine && cmake --install build
|
||||
|
||||
- name: Get Xorg pacman pkgs
|
||||
shell: bash
|
||||
if: inputs.INSTALL_XORG_PKGS == 'true'
|
||||
|
5
.github/workflows/ci.yaml
vendored
@@ -3,6 +3,7 @@ name: Build Hyprland
|
||||
on: [push, pull_request, workflow_dispatch]
|
||||
jobs:
|
||||
gcc:
|
||||
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork
|
||||
name: "Build Hyprland (Arch)"
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
@@ -44,6 +45,7 @@ jobs:
|
||||
path: Hyprland.tar.xz
|
||||
|
||||
meson:
|
||||
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork
|
||||
name: "Build Hyprland with Meson (Arch)"
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
@@ -64,6 +66,7 @@ jobs:
|
||||
run: ninja -C build
|
||||
|
||||
no-pch:
|
||||
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork
|
||||
name: "Build Hyprland without precompiled headers (Arch)"
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
@@ -83,6 +86,7 @@ jobs:
|
||||
run: make nopch
|
||||
|
||||
noxwayland:
|
||||
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork
|
||||
name: "Build Hyprland in pure Wayland (Arch)"
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
@@ -103,6 +107,7 @@ jobs:
|
||||
run: make release
|
||||
|
||||
clang-format:
|
||||
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork
|
||||
name: "Code Style (Arch)"
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
|
18
.github/workflows/nix-build.yml
vendored
@@ -1,3 +1,5 @@
|
||||
name: Nix (Build)
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
secrets:
|
||||
@@ -10,21 +12,17 @@ jobs:
|
||||
matrix:
|
||||
package:
|
||||
- hyprland
|
||||
- hyprland-cross
|
||||
- xdg-desktop-portal-hyprland
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Clone repository
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
ref: ${{ github.ref }}
|
||||
submodules: recursive
|
||||
|
||||
- uses: cachix/install-nix-action@v26
|
||||
- uses: DeterminateSystems/nix-installer-action@main
|
||||
- uses: DeterminateSystems/magic-nix-cache-action@main
|
||||
- uses: cachix/cachix-action@v12
|
||||
|
||||
- uses: cachix/cachix-action@v15
|
||||
with:
|
||||
name: hyprland
|
||||
authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
|
||||
authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}"
|
||||
|
||||
- run: nix build '.?submodules=1#${{ matrix.package }}' -L --extra-substituters "https://hyprland.cachix.org"
|
||||
- run: nix build 'github:hyprwm/Hyprland?ref=${{ github.ref }}#${{ matrix.package }}' -L --extra-substituters "https://hyprland.cachix.org"
|
||||
|
7
.github/workflows/nix-ci.yml
vendored
@@ -1,15 +1,14 @@
|
||||
name: Nix
|
||||
name: Nix (CI)
|
||||
|
||||
on: [push, pull_request, workflow_dispatch]
|
||||
|
||||
jobs:
|
||||
update-inputs:
|
||||
if: github.event_name == 'push' || github.event_name == 'workflow_dispatch'
|
||||
if: (github.event_name == 'push' || github.event_name == 'workflow_dispatch')
|
||||
uses: ./.github/workflows/nix-update-inputs.yml
|
||||
secrets: inherit
|
||||
|
||||
build:
|
||||
if: always() && !cancelled() && !contains(needs.*.result, 'failure')
|
||||
needs: update-inputs
|
||||
if: (github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork)
|
||||
uses: ./.github/workflows/nix-build.yml
|
||||
secrets: inherit
|
||||
|
3
.github/workflows/nix-update-inputs.yml
vendored
@@ -1,4 +1,4 @@
|
||||
name: Nix
|
||||
name: Nix (Update Inputs)
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
@@ -8,6 +8,7 @@ on:
|
||||
|
||||
jobs:
|
||||
update:
|
||||
if: github.repository == 'hyprwm/Hyprland'
|
||||
name: inputs
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
|
1
.github/workflows/security-checks.yml
vendored
@@ -4,6 +4,7 @@ on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
flawfinder:
|
||||
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork
|
||||
name: Flawfinder Checks
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
|
8
.github/workflows/stale.yml
vendored
@@ -7,12 +7,12 @@ name: Mark stale issues and pull requests
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '7 */4 * * *'
|
||||
- cron: "7 */4 * * *"
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
stale:
|
||||
|
||||
if: github.repository == 'hyprwm/Hyprland'
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
issues: write
|
||||
@@ -22,7 +22,7 @@ jobs:
|
||||
- uses: actions/stale@v5
|
||||
with:
|
||||
repo-token: ${{ secrets.STALEBOT_PAT }}
|
||||
stale-issue-label: 'stale'
|
||||
stale-pr-label: 'stale'
|
||||
stale-issue-label: "stale"
|
||||
stale-pr-label: "stale"
|
||||
operations-per-run: 40
|
||||
days-before-close: -1
|
||||
|
10
.gitignore
vendored
@@ -7,6 +7,9 @@ cmake_install.cmake
|
||||
install_manifest.txt
|
||||
compile_commands.json
|
||||
CTestTestfile.cmake
|
||||
CPackConfig.cmake
|
||||
CPackSourceConfig.cmake
|
||||
hyprland.pc
|
||||
_deps
|
||||
|
||||
build/
|
||||
@@ -15,6 +18,9 @@ result*
|
||||
/.idea/
|
||||
.envrc
|
||||
.cache
|
||||
.direnv
|
||||
/.cmake/
|
||||
/.worktree/
|
||||
|
||||
*.o
|
||||
protocols/*.c*
|
||||
@@ -31,5 +37,5 @@ gmon.out
|
||||
PKGBUILD
|
||||
|
||||
src/version.h
|
||||
|
||||
.direnv
|
||||
hyprpm/Makefile
|
||||
hyprctl/Makefile
|
||||
|
4
.gitmodules
vendored
@@ -7,7 +7,3 @@
|
||||
[submodule "subprojects/tracy"]
|
||||
path = subprojects/tracy
|
||||
url = https://github.com/wolfpld/tracy
|
||||
[submodule "subprojects/wlroots-hyprland"]
|
||||
path = subprojects/wlroots-hyprland
|
||||
url = https://github.com/hyprwm/wlroots-hyprland
|
||||
ignore = dirty
|
||||
|
357
CMakeLists.txt
@@ -1,17 +1,16 @@
|
||||
cmake_minimum_required(VERSION 3.27)
|
||||
|
||||
include(CheckIncludeFile)
|
||||
include(ExternalProject)
|
||||
include(GNUInstallDirs)
|
||||
cmake_minimum_required(VERSION 3.30)
|
||||
|
||||
# Get version
|
||||
file(READ ${CMAKE_CURRENT_SOURCE_DIR}/props.json PROPS)
|
||||
string(JSON VER GET ${PROPS} version)
|
||||
file(READ "${CMAKE_SOURCE_DIR}/VERSION" VER_RAW)
|
||||
string(STRIP ${VER_RAW} VER)
|
||||
|
||||
project(Hyprland
|
||||
project(
|
||||
Hyprland
|
||||
DESCRIPTION "A Modern C++ Wayland Compositor"
|
||||
VERSION ${VER}
|
||||
)
|
||||
VERSION ${VER})
|
||||
|
||||
include(CheckIncludeFile)
|
||||
include(GNUInstallDirs)
|
||||
|
||||
set(HYPRLAND_VERSION ${VER})
|
||||
set(PREFIX ${CMAKE_INSTALL_PREFIX})
|
||||
@@ -22,17 +21,22 @@ set(CMAKE_MESSAGE_LOG_LEVEL "STATUS")
|
||||
|
||||
message(STATUS "Gathering git info")
|
||||
|
||||
# Get git info
|
||||
# hash and branch
|
||||
execute_process(
|
||||
COMMAND ./scripts/generateVersion.sh
|
||||
# Get git info hash and branch
|
||||
execute_process(COMMAND ./scripts/generateVersion.sh
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
|
||||
|
||||
# udis
|
||||
add_subdirectory("subprojects/udis86")
|
||||
find_package(PkgConfig REQUIRED)
|
||||
|
||||
# wlroots
|
||||
message(STATUS "Setting up wlroots")
|
||||
# Try to find canihavesomecoffee's udis86 using pkgconfig vmd/udis86 does not
|
||||
# provide a .pc file and won't be detected this way
|
||||
pkg_check_modules(udis_dep IMPORTED_TARGET udis86>=1.7.2)
|
||||
|
||||
# Fallback to subproject
|
||||
if(NOT udis_dep_FOUND)
|
||||
add_subdirectory("subprojects/udis86")
|
||||
include_directories("subprojects/udis86")
|
||||
message(STATUS "udis86 dependency not found, falling back to subproject")
|
||||
endif()
|
||||
|
||||
if(CMAKE_BUILD_TYPE)
|
||||
string(TOLOWER ${CMAKE_BUILD_TYPE} BUILDTYPE_LOWER)
|
||||
@@ -53,25 +57,11 @@ else()
|
||||
set(BUILDTYPE_LOWER "release")
|
||||
endif()
|
||||
|
||||
ExternalProject_Add(
|
||||
wlroots-hyprland
|
||||
PREFIX ${CMAKE_SOURCE_DIR}/subprojects/wlroots-hyprland
|
||||
SOURCE_DIR ${CMAKE_SOURCE_DIR}/subprojects/wlroots-hyprland
|
||||
CONFIGURE_COMMAND meson setup --reconfigure build --buildtype=${BUILDTYPE_LOWER} -Dwerror=false -Dxwayland=$<IF:$<BOOL:${NO_XWAYLAND}>,disabled,enabled> -Dexamples=false -Drenderers=gles2 -Dbackends=drm,libinput $<IF:$<BOOL:${WITH_ASAN}>,-Db_sanitize=address,-Db_sanitize=none>
|
||||
BUILD_COMMAND ninja -C build
|
||||
BUILD_ALWAYS true
|
||||
BUILD_IN_SOURCE true
|
||||
BUILD_BYPRODUCTS ${CMAKE_SOURCE_DIR}/subprojects/wlroots-hyprland/build/libwlroots.a
|
||||
INSTALL_COMMAND echo "wlroots-hyprland: install not needed"
|
||||
)
|
||||
|
||||
find_package(PkgConfig REQUIRED)
|
||||
|
||||
pkg_get_variable(WaylandScanner wayland-scanner wayland_scanner)
|
||||
message(STATUS "Found WaylandScanner at ${WaylandScanner}")
|
||||
pkg_get_variable(WAYLAND_PROTOCOLS_DIR wayland-protocols pkgdatadir)
|
||||
message(STATUS "Found wayland-protocols at ${WAYLAND_PROTOCOLS_DIR}")
|
||||
pkg_get_variable(WAYLAND_SERVER_DIR wayland-server pkgdatadir)
|
||||
pkg_get_variable(WAYLAND_SCANNER_PKGDATA_DIR wayland-scanner pkgdatadir)
|
||||
message(
|
||||
STATUS "Found wayland-scanner pkgdatadir at ${WAYLAND_SCANNER_PKGDATA_DIR}")
|
||||
|
||||
if(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG)
|
||||
message(STATUS "Configuring Hyprland in Debug with CMake")
|
||||
@@ -81,17 +71,17 @@ else()
|
||||
message(STATUS "Configuring Hyprland in Release with CMake")
|
||||
endif()
|
||||
|
||||
include_directories(
|
||||
.
|
||||
"src/"
|
||||
"subprojects/wlroots-hyprland/include/"
|
||||
"subprojects/wlroots-hyprland/build/include/"
|
||||
"subprojects/udis86/"
|
||||
"protocols/")
|
||||
set(CMAKE_CXX_STANDARD 23)
|
||||
add_compile_definitions(WLR_USE_UNSTABLE)
|
||||
add_compile_options(-Wall -Wextra -Wno-unused-parameter -Wno-unused-value
|
||||
-Wno-missing-field-initializers -Wno-narrowing -Wno-pointer-arith
|
||||
include_directories(. "src/" "protocols/")
|
||||
|
||||
set(CMAKE_CXX_STANDARD 26)
|
||||
add_compile_options(
|
||||
-Wall
|
||||
-Wextra
|
||||
-Wno-unused-parameter
|
||||
-Wno-unused-value
|
||||
-Wno-missing-field-initializers
|
||||
-Wno-narrowing
|
||||
-Wno-pointer-arith
|
||||
-fmacro-prefix-map=${CMAKE_SOURCE_DIR}/=)
|
||||
|
||||
set(CMAKE_EXECUTABLE_ENABLE_EXPORTS TRUE)
|
||||
@@ -108,13 +98,32 @@ else()
|
||||
endif()
|
||||
find_package(OpenGL REQUIRED COMPONENTS ${GLES_VERSION})
|
||||
|
||||
pkg_check_modules(deps REQUIRED IMPORTED_TARGET
|
||||
xkbcommon uuid
|
||||
wayland-server wayland-client wayland-cursor wayland-protocols
|
||||
cairo pango pangocairo pixman-1
|
||||
libdrm libinput hwdata libseat libdisplay-info libliftoff libudev gbm
|
||||
hyprlang>=0.3.2 hyprcursor>=0.1.7
|
||||
)
|
||||
pkg_check_modules(hyprctl_deps REQUIRED IMPORTED_TARGET hyprutils>=0.2.1)
|
||||
|
||||
pkg_check_modules(aquamarine_dep REQUIRED IMPORTED_TARGET aquamarine)
|
||||
|
||||
add_compile_definitions(AQUAMARINE_VERSION="${aquamarine_dep_VERSION}")
|
||||
|
||||
pkg_check_modules(
|
||||
deps
|
||||
REQUIRED
|
||||
IMPORTED_TARGET
|
||||
xkbcommon
|
||||
uuid
|
||||
wayland-server>=1.22.90
|
||||
wayland-protocols
|
||||
cairo
|
||||
pango
|
||||
pangocairo
|
||||
pixman-1
|
||||
xcursor
|
||||
libdrm
|
||||
libinput
|
||||
gbm
|
||||
gio-2.0
|
||||
hyprlang>=0.3.2
|
||||
hyprcursor>=0.1.7
|
||||
hyprutils>=0.2.3)
|
||||
|
||||
find_package(hyprwayland-scanner 0.3.10 REQUIRED)
|
||||
|
||||
@@ -127,14 +136,13 @@ if(USE_TRACY)
|
||||
endif()
|
||||
|
||||
add_executable(Hyprland ${SRCFILES} ${TRACY_CPP_FILES})
|
||||
add_dependencies(Hyprland wlroots-hyprland)
|
||||
|
||||
set(USE_GPROF ON)
|
||||
|
||||
if(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG)
|
||||
message(STATUS "Setting debug flags")
|
||||
|
||||
if (WITH_ASAN)
|
||||
if(WITH_ASAN)
|
||||
message(STATUS "Enabling ASan")
|
||||
|
||||
target_link_libraries(Hyprland asan)
|
||||
@@ -144,9 +152,9 @@ if(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG)
|
||||
if(USE_TRACY)
|
||||
message(STATUS "Tracy is turned on")
|
||||
|
||||
option( TRACY_ENABLE "" ON)
|
||||
option( TRACY_ON_DEMAND "" ON)
|
||||
add_subdirectory (subprojects/tracy)
|
||||
option(TRACY_ENABLE "" ON)
|
||||
option(TRACY_ON_DEMAND "" ON)
|
||||
add_subdirectory(subprojects/tracy)
|
||||
|
||||
target_link_libraries(Hyprland Tracy::TracyClient)
|
||||
|
||||
@@ -192,7 +200,17 @@ if(NO_XWAYLAND)
|
||||
add_compile_definitions(NO_XWAYLAND)
|
||||
else()
|
||||
message(STATUS "XWAYLAND Enabled (NO_XWAYLAND not defined) checking deps...")
|
||||
pkg_check_modules(xdeps REQUIRED IMPORTED_TARGET xcb xwayland xcb-util xcb-render xcb-xfixes xcb-icccm xcb-composite xcb-res xcb-ewmh xcb-errors)
|
||||
pkg_check_modules(
|
||||
xdeps
|
||||
REQUIRED
|
||||
IMPORTED_TARGET
|
||||
xcb
|
||||
xcb-render
|
||||
xcb-xfixes
|
||||
xcb-icccm
|
||||
xcb-composite
|
||||
xcb-res
|
||||
xcb-errors)
|
||||
target_link_libraries(Hyprland PkgConfig::xdeps)
|
||||
endif()
|
||||
|
||||
@@ -209,113 +227,112 @@ include(CPack)
|
||||
|
||||
message(STATUS "Setting precompiled headers")
|
||||
|
||||
target_precompile_headers(Hyprland PRIVATE $<$<COMPILE_LANGUAGE:CXX>:src/pch/pch.hpp>)
|
||||
target_precompile_headers(Hyprland PRIVATE
|
||||
$<$<COMPILE_LANGUAGE:CXX>:src/pch/pch.hpp>)
|
||||
|
||||
message(STATUS "Setting link libraries")
|
||||
|
||||
target_link_libraries(Hyprland rt PkgConfig::deps)
|
||||
target_link_libraries(Hyprland rt PkgConfig::aquamarine_dep PkgConfig::deps)
|
||||
if(udis_dep_FOUND)
|
||||
target_link_libraries(Hyprland PkgConfig::udis_dep)
|
||||
else()
|
||||
target_link_libraries(Hyprland libudis86)
|
||||
endif()
|
||||
|
||||
# used by `make installheaders`, to ensure the headers are generated
|
||||
add_custom_target(generate-protocol-headers)
|
||||
|
||||
function(protocol protoPath protoName external)
|
||||
if (external)
|
||||
set(path ${CMAKE_SOURCE_DIR}/${protoPath})
|
||||
else()
|
||||
set(path ${WAYLAND_PROTOCOLS_DIR}/${protoPath})
|
||||
endif()
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${CMAKE_SOURCE_DIR}/protocols/${protoName}-protocol.h
|
||||
COMMAND ${WaylandScanner} server-header ${path} protocols/${protoName}-protocol.h
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||
)
|
||||
add_custom_command(
|
||||
OUTPUT ${CMAKE_SOURCE_DIR}/protocols/${protoName}-protocol.c
|
||||
COMMAND ${WaylandScanner} private-code ${path} protocols/${protoName}-protocol.c
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||
)
|
||||
target_sources(Hyprland PRIVATE ${CMAKE_SOURCE_DIR}/protocols/${protoName}-protocol.h ${CMAKE_SOURCE_DIR}/protocols/${protoName}-protocol.c)
|
||||
target_sources(generate-protocol-headers PRIVATE ${CMAKE_SOURCE_DIR}/protocols/${protoName}-protocol.h)
|
||||
endfunction()
|
||||
|
||||
function(protocolNew protoPath protoName external)
|
||||
if (external)
|
||||
set(path ${CMAKE_SOURCE_DIR}/${protoPath})
|
||||
function(protocolnew protoPath protoName external)
|
||||
if(external)
|
||||
set(path ${protoPath})
|
||||
else()
|
||||
set(path ${WAYLAND_PROTOCOLS_DIR}/${protoPath})
|
||||
endif()
|
||||
add_custom_command(
|
||||
OUTPUT ${CMAKE_SOURCE_DIR}/protocols/${protoName}.cpp
|
||||
${CMAKE_SOURCE_DIR}/protocols/${protoName}.hpp
|
||||
COMMAND hyprwayland-scanner ${path}/${protoName}.xml ${CMAKE_SOURCE_DIR}/protocols/
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||
)
|
||||
target_sources(Hyprland PRIVATE protocols/${protoName}.cpp protocols/${protoName}.hpp)
|
||||
target_sources(generate-protocol-headers PRIVATE ${CMAKE_SOURCE_DIR}/protocols/${protoName}.hpp)
|
||||
COMMAND hyprwayland-scanner ${path}/${protoName}.xml
|
||||
${CMAKE_SOURCE_DIR}/protocols/
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
|
||||
target_sources(Hyprland PRIVATE protocols/${protoName}.cpp
|
||||
protocols/${protoName}.hpp)
|
||||
target_sources(generate-protocol-headers
|
||||
PRIVATE ${CMAKE_SOURCE_DIR}/protocols/${protoName}.hpp)
|
||||
endfunction()
|
||||
function(protocolWayland)
|
||||
add_custom_command(
|
||||
OUTPUT ${CMAKE_SOURCE_DIR}/protocols/wayland.cpp
|
||||
${CMAKE_SOURCE_DIR}/protocols/wayland.hpp
|
||||
COMMAND hyprwayland-scanner --wayland-enums ${WAYLAND_SERVER_DIR}/wayland.xml ${CMAKE_SOURCE_DIR}/protocols/
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||
)
|
||||
COMMAND
|
||||
hyprwayland-scanner --wayland-enums
|
||||
${WAYLAND_SCANNER_PKGDATA_DIR}/wayland.xml ${CMAKE_SOURCE_DIR}/protocols/
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
|
||||
target_sources(Hyprland PRIVATE protocols/wayland.cpp protocols/wayland.hpp)
|
||||
target_sources(generate-protocol-headers PRIVATE ${CMAKE_SOURCE_DIR}/protocols/wayland.hpp)
|
||||
target_sources(generate-protocol-headers
|
||||
PRIVATE ${CMAKE_SOURCE_DIR}/protocols/wayland.hpp)
|
||||
endfunction()
|
||||
|
||||
target_link_libraries(Hyprland
|
||||
${CMAKE_SOURCE_DIR}/subprojects/wlroots-hyprland/build/libwlroots.a
|
||||
OpenGL::EGL
|
||||
OpenGL::GL
|
||||
Threads::Threads
|
||||
libudis86
|
||||
uuid
|
||||
)
|
||||
target_link_libraries(Hyprland OpenGL::EGL OpenGL::GL Threads::Threads)
|
||||
|
||||
protocol("protocols/wlr-screencopy-unstable-v1.xml" "wlr-screencopy-unstable-v1" true)
|
||||
protocol("subprojects/hyprland-protocols/protocols/hyprland-global-shortcuts-v1.xml" "hyprland-global-shortcuts-v1" true)
|
||||
protocol("subprojects/hyprland-protocols/protocols/hyprland-toplevel-export-v1.xml" "hyprland-toplevel-export-v1" true)
|
||||
protocol("unstable/text-input/text-input-unstable-v1.xml" "text-input-unstable-v1" false)
|
||||
pkg_check_modules(hyprland_protocols_dep hyprland-protocols>=0.2.0)
|
||||
if(hyprland_protocols_dep_FOUND)
|
||||
pkg_get_variable(HYPRLAND_PROTOCOLS hyprland-protocols pkgdatadir)
|
||||
message(STATUS "hyprland-protocols dependency set to ${HYPRLAND_PROTOCOLS}")
|
||||
else()
|
||||
set(HYPRLAND_PROTOCOLS "subprojects/hyprland-protocols")
|
||||
message(STATUS "hyprland-protocols subproject set to ${HYPRLAND_PROTOCOLS}")
|
||||
endif()
|
||||
|
||||
protocolNew("protocols" "wlr-gamma-control-unstable-v1" true)
|
||||
protocolNew("protocols" "wlr-foreign-toplevel-management-unstable-v1" true)
|
||||
protocolNew("protocols" "wlr-output-power-management-unstable-v1" true)
|
||||
protocolNew("protocols" "virtual-keyboard-unstable-v1" true)
|
||||
protocolNew("protocols" "wlr-virtual-pointer-unstable-v1" true)
|
||||
protocolNew("protocols" "input-method-unstable-v2" true)
|
||||
protocolNew("protocols" "wlr-output-management-unstable-v1" true)
|
||||
protocolNew("protocols" "kde-server-decoration" true)
|
||||
protocolNew("protocols" "wlr-data-control-unstable-v1" true)
|
||||
protocolNew("subprojects/hyprland-protocols/protocols" "hyprland-focus-grab-v1" true)
|
||||
protocolNew("protocols" "wlr-layer-shell-unstable-v1" true)
|
||||
protocolNew("protocols" "wayland-drm" true)
|
||||
protocolNew("staging/tearing-control" "tearing-control-v1" false)
|
||||
protocolNew("staging/fractional-scale" "fractional-scale-v1" false)
|
||||
protocolNew("unstable/xdg-output" "xdg-output-unstable-v1" false)
|
||||
protocolNew("staging/cursor-shape" "cursor-shape-v1" false)
|
||||
protocolNew("unstable/idle-inhibit" "idle-inhibit-unstable-v1" false)
|
||||
protocolNew("unstable/relative-pointer" "relative-pointer-unstable-v1" false)
|
||||
protocolNew("unstable/xdg-decoration" "xdg-decoration-unstable-v1" false)
|
||||
protocolNew("staging/alpha-modifier" "alpha-modifier-v1" false)
|
||||
protocolNew("staging/ext-foreign-toplevel-list" "ext-foreign-toplevel-list-v1" false)
|
||||
protocolNew("unstable/pointer-gestures" "pointer-gestures-unstable-v1" false)
|
||||
protocolNew("unstable/keyboard-shortcuts-inhibit" "keyboard-shortcuts-inhibit-unstable-v1" false)
|
||||
protocolNew("unstable/text-input" "text-input-unstable-v3" false)
|
||||
protocolNew("unstable/pointer-constraints" "pointer-constraints-unstable-v1" false)
|
||||
protocolNew("staging/xdg-activation" "xdg-activation-v1" false)
|
||||
protocolNew("staging/ext-idle-notify" "ext-idle-notify-v1" false)
|
||||
protocolNew("staging/ext-session-lock" "ext-session-lock-v1" false)
|
||||
protocolNew("stable/tablet" "tablet-v2" false)
|
||||
protocolNew("stable/presentation-time" "presentation-time" false)
|
||||
protocolNew("stable/xdg-shell" "xdg-shell" false)
|
||||
protocolNew("unstable/primary-selection" "primary-selection-unstable-v1" false)
|
||||
protocolNew("staging/xwayland-shell" "xwayland-shell-v1" false)
|
||||
protocolNew("stable/viewporter" "viewporter" false)
|
||||
protocolNew("stable/linux-dmabuf" "linux-dmabuf-v1" false)
|
||||
protocolnew("${HYPRLAND_PROTOCOLS}/protocols" "hyprland-global-shortcuts-v1"
|
||||
true)
|
||||
protocolnew("unstable/text-input" "text-input-unstable-v1" false)
|
||||
protocolnew("${HYPRLAND_PROTOCOLS}/protocols" "hyprland-toplevel-export-v1"
|
||||
true)
|
||||
protocolnew("protocols" "wlr-screencopy-unstable-v1" true)
|
||||
protocolnew("protocols" "wlr-gamma-control-unstable-v1" true)
|
||||
protocolnew("protocols" "wlr-foreign-toplevel-management-unstable-v1" true)
|
||||
protocolnew("protocols" "wlr-output-power-management-unstable-v1" true)
|
||||
protocolnew("protocols" "virtual-keyboard-unstable-v1" true)
|
||||
protocolnew("protocols" "wlr-virtual-pointer-unstable-v1" true)
|
||||
protocolnew("protocols" "input-method-unstable-v2" true)
|
||||
protocolnew("protocols" "wlr-output-management-unstable-v1" true)
|
||||
protocolnew("protocols" "kde-server-decoration" true)
|
||||
protocolnew("protocols" "wlr-data-control-unstable-v1" true)
|
||||
protocolnew("${HYPRLAND_PROTOCOLS}/protocols" "hyprland-focus-grab-v1" true)
|
||||
protocolnew("protocols" "wlr-layer-shell-unstable-v1" true)
|
||||
protocolnew("protocols" "wayland-drm" true)
|
||||
protocolnew("staging/tearing-control" "tearing-control-v1" false)
|
||||
protocolnew("staging/fractional-scale" "fractional-scale-v1" false)
|
||||
protocolnew("unstable/xdg-output" "xdg-output-unstable-v1" false)
|
||||
protocolnew("staging/cursor-shape" "cursor-shape-v1" false)
|
||||
protocolnew("unstable/idle-inhibit" "idle-inhibit-unstable-v1" false)
|
||||
protocolnew("unstable/relative-pointer" "relative-pointer-unstable-v1" false)
|
||||
protocolnew("unstable/xdg-decoration" "xdg-decoration-unstable-v1" false)
|
||||
protocolnew("staging/alpha-modifier" "alpha-modifier-v1" false)
|
||||
protocolnew("staging/ext-foreign-toplevel-list" "ext-foreign-toplevel-list-v1"
|
||||
false)
|
||||
protocolnew("unstable/pointer-gestures" "pointer-gestures-unstable-v1" false)
|
||||
protocolnew("unstable/keyboard-shortcuts-inhibit"
|
||||
"keyboard-shortcuts-inhibit-unstable-v1" false)
|
||||
protocolnew("unstable/text-input" "text-input-unstable-v3" false)
|
||||
protocolnew("unstable/pointer-constraints" "pointer-constraints-unstable-v1"
|
||||
false)
|
||||
protocolnew("staging/xdg-activation" "xdg-activation-v1" false)
|
||||
protocolnew("staging/ext-idle-notify" "ext-idle-notify-v1" false)
|
||||
protocolnew("staging/ext-session-lock" "ext-session-lock-v1" false)
|
||||
protocolnew("stable/tablet" "tablet-v2" false)
|
||||
protocolnew("stable/presentation-time" "presentation-time" false)
|
||||
protocolnew("stable/xdg-shell" "xdg-shell" false)
|
||||
protocolnew("unstable/primary-selection" "primary-selection-unstable-v1" false)
|
||||
protocolnew("staging/xwayland-shell" "xwayland-shell-v1" false)
|
||||
protocolnew("stable/viewporter" "viewporter" false)
|
||||
protocolnew("stable/linux-dmabuf" "linux-dmabuf-v1" false)
|
||||
protocolnew("staging/drm-lease" "drm-lease-v1" false)
|
||||
protocolnew("staging/linux-drm-syncobj" "linux-drm-syncobj-v1" false)
|
||||
protocolnew("staging/xdg-dialog" "xdg-dialog-v1" false)
|
||||
protocolnew("staging/single-pixel-buffer" "single-pixel-buffer-v1" false)
|
||||
|
||||
protocolWayland()
|
||||
protocolwayland()
|
||||
|
||||
# tools
|
||||
add_subdirectory(hyprctl)
|
||||
@@ -324,60 +341,54 @@ add_subdirectory(hyprpm)
|
||||
# binary and symlink
|
||||
install(TARGETS Hyprland)
|
||||
|
||||
install(CODE "execute_process( \
|
||||
install(
|
||||
CODE "execute_process( \
|
||||
COMMAND ${CMAKE_COMMAND} -E create_symlink \
|
||||
${CMAKE_INSTALL_BINDIR}/Hyprland \
|
||||
${CMAKE_INSTALL_BINDIR}/hyprland
|
||||
)"
|
||||
)
|
||||
${CMAKE_INSTALL_FULL_BINDIR}/Hyprland \
|
||||
\"\$ENV{DESTDIR}${CMAKE_INSTALL_FULL_BINDIR}/hyprland\" \
|
||||
)")
|
||||
|
||||
# session file
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/example/hyprland.desktop
|
||||
DESTINATION ${CMAKE_INSTALL_DATADIR}/wayland-sessions)
|
||||
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/wayland-sessions)
|
||||
|
||||
# wallpapers
|
||||
file(GLOB_RECURSE WALLPAPERS "assets/wall*")
|
||||
install(FILES ${WALLPAPERS}
|
||||
DESTINATION ${CMAKE_INSTALL_DATADIR}/hyprland)
|
||||
# allow Hyprland to find assets
|
||||
add_compile_definitions(DATAROOTDIR="${CMAKE_INSTALL_FULL_DATAROOTDIR}")
|
||||
|
||||
# installable assets
|
||||
file(GLOB_RECURSE INSTALLABLE_ASSETS "assets/install/*")
|
||||
list(FILTER INSTALLABLE_ASSETS EXCLUDE REGEX "meson.build")
|
||||
install(FILES ${INSTALLABLE_ASSETS}
|
||||
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/hypr)
|
||||
|
||||
# default config
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/example/hyprland.conf
|
||||
DESTINATION ${CMAKE_INSTALL_DATADIR}/hyprland)
|
||||
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/hypr)
|
||||
|
||||
# portal config
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/assets/hyprland-portals.conf
|
||||
DESTINATION ${CMAKE_INSTALL_DATADIR}/xdg-desktop-portal)
|
||||
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/xdg-desktop-portal)
|
||||
|
||||
# man pages
|
||||
file(GLOB_RECURSE MANPAGES "docs/*.1")
|
||||
install(FILES ${MANPAGES}
|
||||
DESTINATION ${CMAKE_INSTALL_MANDIR}/man1)
|
||||
|
||||
install(FILES ${MANPAGES} DESTINATION ${CMAKE_INSTALL_MANDIR}/man1)
|
||||
|
||||
# pkgconfig entry
|
||||
install(FILES ${CMAKE_BINARY_DIR}/hyprland.pc
|
||||
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/pkgconfig)
|
||||
|
||||
# wlroots headers
|
||||
set(HEADERS_WLR "${CMAKE_CURRENT_SOURCE_DIR}/subprojects/wlroots-hyprland/include/wlr")
|
||||
install(DIRECTORY ${HEADERS_WLR}
|
||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/hyprland
|
||||
FILES_MATCHING PATTERN "*.h")
|
||||
|
||||
# config.h and version.h
|
||||
set(HEADERS_WLR_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/subprojects/wlroots-hyprland/build/include/wlr")
|
||||
install(DIRECTORY ${HEADERS_WLR_ROOT}/
|
||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/hyprland/wlr
|
||||
FILES_MATCHING PATTERN "*.h")
|
||||
|
||||
# protocol headers
|
||||
set(HEADERS_PROTO "${CMAKE_CURRENT_SOURCE_DIR}/protocols")
|
||||
install(DIRECTORY ${HEADERS_PROTO}
|
||||
install(
|
||||
DIRECTORY ${HEADERS_PROTO}
|
||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/hyprland
|
||||
FILES_MATCHING PATTERN "*.h*")
|
||||
FILES_MATCHING
|
||||
PATTERN "*.h*")
|
||||
|
||||
# hyprland headers
|
||||
set(HEADERS_SRC "${CMAKE_CURRENT_SOURCE_DIR}/src")
|
||||
install(DIRECTORY ${HEADERS_SRC}
|
||||
install(
|
||||
DIRECTORY ${HEADERS_SRC}
|
||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/hyprland
|
||||
FILES_MATCHING PATTERN "*.h*")
|
||||
FILES_MATCHING
|
||||
PATTERN "*.h*")
|
||||
|
34
Makefile
@@ -1,33 +1,28 @@
|
||||
PREFIX = /usr/local
|
||||
|
||||
legacyrenderer:
|
||||
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -DLEGACY_RENDERER:BOOL=true -S . -B ./build -G Ninja
|
||||
cmake --build ./build --config Release --target all
|
||||
chmod -R 777 ./build
|
||||
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -DLEGACY_RENDERER:BOOL=true -S . -B ./buildZ
|
||||
cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
|
||||
|
||||
legacyrendererdebug:
|
||||
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Debug -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -DLEGACY_RENDERER:BOOL=true -S . -B ./build -G Ninja
|
||||
cmake --build ./build --config Release --target all
|
||||
chmod -R 777 ./build
|
||||
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Debug -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -DLEGACY_RENDERER:BOOL=true -S . -B ./build
|
||||
cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
|
||||
|
||||
release:
|
||||
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -S . -B ./build -G Ninja
|
||||
cmake --build ./build --config Release --target all
|
||||
chmod -R 777 ./build
|
||||
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -S . -B ./build
|
||||
cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
|
||||
|
||||
debug:
|
||||
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Debug -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -S . -B ./build -G Ninja
|
||||
cmake --build ./build --config Debug --target all
|
||||
chmod -R 777 ./build
|
||||
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Debug -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -S . -B ./build
|
||||
cmake --build ./build --config Debug --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
|
||||
|
||||
nopch:
|
||||
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -DCMAKE_DISABLE_PRECOMPILE_HEADERS=ON -S . -B ./build -G Ninja
|
||||
cmake --build ./build --config Release --target all
|
||||
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -DCMAKE_DISABLE_PRECOMPILE_HEADERS=ON -S . -B ./build
|
||||
cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
|
||||
|
||||
clear:
|
||||
rm -rf build
|
||||
rm -f ./protocols/*.h ./protocols/*.c ./protocols/*.cpp ./protocols/*.hpp
|
||||
rm -rf ./subprojects/wlroots-hyprland/build
|
||||
|
||||
all:
|
||||
$(MAKE) clear
|
||||
@@ -50,14 +45,11 @@ installheaders:
|
||||
rm -fr ${PREFIX}/include/hyprland
|
||||
mkdir -p ${PREFIX}/include/hyprland
|
||||
mkdir -p ${PREFIX}/include/hyprland/protocols
|
||||
mkdir -p ${PREFIX}/include/hyprland/wlr
|
||||
mkdir -p ${PREFIX}/share/pkgconfig
|
||||
|
||||
cmake --build ./build --config Release --target generate-protocol-headers
|
||||
|
||||
find src -name '*.h*' -print0 | cpio --quiet -0dump ${PREFIX}/include/hyprland
|
||||
cd subprojects/wlroots-hyprland/include/wlr && find . -name '*.h*' -print0 | cpio --quiet -0dump ${PREFIX}/include/hyprland/wlr && cd ../../../..
|
||||
cd subprojects/wlroots-hyprland/build/include && find . -name '*.h*' -print0 | cpio --quiet -0dump ${PREFIX}/include/hyprland/wlr && cd ../../../..
|
||||
cp ./protocols/*.h* ${PREFIX}/include/hyprland/protocols
|
||||
cp ./build/hyprland.pc ${PREFIX}/share/pkgconfig
|
||||
if [ -d /usr/share/pkgconfig ]; then cp ./build/hyprland.pc /usr/share/pkgconfig 2>/dev/null || true; fi
|
||||
@@ -88,11 +80,11 @@ asan:
|
||||
@pidof Hyprland > /dev/null && exit 1 || echo ""
|
||||
|
||||
rm -rf ./wayland
|
||||
git reset --hard
|
||||
#git reset --hard
|
||||
|
||||
@echo -en "If you want to apply a patch, input its path (leave empty for none):\n"
|
||||
@read patchvar
|
||||
@if [-n "$patchvar"]; then patch -p1 < $patchvar || echo ""; else echo "No patch specified"; fi
|
||||
@read patchvar; \
|
||||
if [ -n "$$patchvar" ]; then patch -p1 < "$$patchvar" || echo ""; else echo "No patch specified"; fi
|
||||
|
||||
git clone --recursive https://gitlab.freedesktop.org/wayland/wayland
|
||||
cd wayland && patch -p1 < ../scripts/waylandStatic.diff && meson setup build --buildtype=debug -Db_sanitize=address -Ddocumentation=false && ninja -C build && cd ..
|
||||
|
12
README.md
@@ -1,6 +1,6 @@
|
||||
<div align = center>
|
||||
|
||||
<img src="https://raw.githubusercontent.com/vaxerski/Hyprland/main/assets/header.svg" width="750" height="300" alt="banner">
|
||||
<img src="https://raw.githubusercontent.com/hyprwm/Hyprland/main/assets/header.svg" width="750" height="300" alt="banner">
|
||||
|
||||
<br>
|
||||
|
||||
@@ -13,10 +13,10 @@
|
||||
|
||||
<br>
|
||||
|
||||
Hyprland is a dynamic tiling Wayland compositor based on wlroots that doesn't sacrifice on its looks.
|
||||
Hyprland is a 100% independent, dynamic tiling Wayland compositor that doesn't sacrifice on its looks.
|
||||
|
||||
It provides the latest Wayland features, is highly customizable, has all the eyecandy, the most powerful plugins,
|
||||
easy IPC, much more QoL stuff than other wlr-based compositors and more...
|
||||
easy IPC, much more QoL stuff than other compositors and more...
|
||||
<br>
|
||||
<br>
|
||||
|
||||
@@ -37,7 +37,7 @@ easy IPC, much more QoL stuff than other wlr-based compositors and more...
|
||||
|
||||
- All of the eyecandy: gradient borders, blur, animations, shadows and much more
|
||||
- A lot of customization
|
||||
- Much more QoL stuff than other wlr-based compositors
|
||||
- 100% independent, no wlroots, no libweston, no kwin, no mutter.
|
||||
- Custom bezier curves for the best animations
|
||||
- Powerful plugin support
|
||||
- Built-in plugin manager
|
||||
@@ -48,7 +48,6 @@ easy IPC, much more QoL stuff than other wlr-based compositors and more...
|
||||
- Config reloaded instantly upon saving
|
||||
- Fully dynamic workspaces
|
||||
- Two built-in layouts and more available as plugins
|
||||
- Uses forked wlroots with QoL patches
|
||||
- Global keybinds passed to your apps of choice
|
||||
- Tiling/pseudotiling/floating/fullscreen windows
|
||||
- Special workspaces (scratchpads)
|
||||
@@ -86,7 +85,7 @@ easy IPC, much more QoL stuff than other wlr-based compositors and more...
|
||||
|
||||
<br>
|
||||
|
||||
**[wlroots]** - *For their amazing library*
|
||||
**[wlroots]** - *For powering Hyprland in the past*
|
||||
|
||||
**[tinywl]** - *For showing how 2 do stuff*
|
||||
|
||||
@@ -126,7 +125,6 @@ easy IPC, much more QoL stuff than other wlr-based compositors and more...
|
||||
|
||||
<!----------------------------------{ Images }--------------------------------->
|
||||
|
||||
[Stars Preview]: https://starchart.cc/vaxerski/Hyprland.svg
|
||||
[Preview A]: https://i.ibb.co/C1yTb0r/falf.png
|
||||
[Preview B]: https://linfindel.github.io/cdn/hyprland-preview-b.png
|
||||
[Preview C]: https://i.ibb.co/B3GJg28/20221126-20h53m26s-grim.png
|
||||
|
BIN
assets/install/lockdead.png
Normal file
After Width: | Height: | Size: 110 KiB |
BIN
assets/install/lockdead2.png
Normal file
After Width: | Height: | Size: 48 KiB |
10
assets/install/meson.build
Normal file
@@ -0,0 +1,10 @@
|
||||
globber = run_command('sh', '-c', 'find . -type f -not -name "*.build"', check: true)
|
||||
files = globber.stdout().strip().split('\n')
|
||||
|
||||
foreach file : files
|
||||
install_data(
|
||||
file,
|
||||
install_dir: join_paths(get_option('datadir'), 'hypr'),
|
||||
install_tag: 'runtime',
|
||||
)
|
||||
endforeach
|
Before Width: | Height: | Size: 14 MiB After Width: | Height: | Size: 14 MiB |
Before Width: | Height: | Size: 5.9 MiB After Width: | Height: | Size: 5.9 MiB |
Before Width: | Height: | Size: 27 MiB After Width: | Height: | Size: 27 MiB |
@@ -1,7 +1,7 @@
|
||||
wallpapers = ['0', '1', '2']
|
||||
install_data(
|
||||
'hyprland-portals.conf',
|
||||
install_dir: join_paths(get_option('datadir'), 'xdg-desktop-portal'),
|
||||
install_tag: 'runtime',
|
||||
)
|
||||
|
||||
foreach type : wallpapers
|
||||
install_data(f'wall@type@.png', install_dir: join_paths(get_option('datadir'), 'hyprland'), install_tag: 'runtime')
|
||||
endforeach
|
||||
|
||||
install_data('hyprland-portals.conf', install_dir: join_paths(get_option('datadir'), 'xdg-desktop-portal'), install_tag: 'runtime')
|
||||
subdir('install')
|
||||
|
@@ -10,8 +10,8 @@ Hyprland - Dynamic tiling Wayland compositor
|
||||
\f[B]Hyprland\f[R] [\f[I]arg [...]\f[R]].
|
||||
.SH DESCRIPTION
|
||||
.PP
|
||||
\f[B]Hyprland\f[R] is a dynamic tiling Wayland compositor based on
|
||||
wlroots that doesn\[aq]t sacrifice on its looks.
|
||||
\f[B]Hyprland\f[R] is an independent, highly customizable, dynamic
|
||||
tiling Wayland compositor that doesn\[aq]t sacrifice on its looks.
|
||||
.PP
|
||||
You can launch Hyprland by either going into a TTY and executing
|
||||
\f[B]Hyprland\f[R], or with a login manager.
|
||||
@@ -32,6 +32,12 @@ Show command usage.
|
||||
.TP
|
||||
\f[B]-c\f[R], \f[B]--config\f[R]
|
||||
Specify config file to use.
|
||||
.TP
|
||||
\f[B]--socket\f[R]
|
||||
Sets the Wayland socket name (for Wayland socket handover)
|
||||
.TP
|
||||
\f[B]--wayland-fd\f[R]
|
||||
Sets the Wayland socket file descriptor (for Wayland socket handover)
|
||||
.SH BUGS
|
||||
.TP
|
||||
Submit bug reports and request features online at:
|
||||
|
@@ -14,8 +14,8 @@ SYNOPSIS
|
||||
DESCRIPTION
|
||||
===========
|
||||
|
||||
**Hyprland** is a dynamic tiling Wayland compositor based on
|
||||
wlroots that doesn't sacrifice on its looks.
|
||||
**Hyprland** is an independent, highly customizable,
|
||||
dynamic tiling Wayland compositor that doesn't sacrifice on its looks.
|
||||
|
||||
You can launch Hyprland by either going into a TTY and
|
||||
executing **Hyprland**, or with a login manager.
|
||||
@@ -41,6 +41,12 @@ OPTIONS
|
||||
**-c**, **--config**
|
||||
Specify config file to use.
|
||||
|
||||
**--socket**
|
||||
Sets the Wayland socket name (for Wayland socket handover)
|
||||
|
||||
**--wayland-fd**
|
||||
Sets the Wayland socket file descriptor (for Wayland socket handover)
|
||||
|
||||
BUGS
|
||||
====
|
||||
|
||||
|
@@ -1,2 +1,2 @@
|
||||
install_man ('Hyprland.1')
|
||||
install_man ('hyprctl.1')
|
||||
install_man('Hyprland.1')
|
||||
install_man('hyprctl.1')
|
||||
|
14
example/hyprland-session.service
Normal file
@@ -0,0 +1,14 @@
|
||||
[Unit]
|
||||
Description=Hyprland - Tiling compositor with the looks
|
||||
Documentation=man:Hyprland(1)
|
||||
BindsTo=graphical-session.target
|
||||
Before=graphical-session.target
|
||||
Wants=graphical-session-pre.target
|
||||
After=graphical-session-pre.target
|
||||
|
||||
[Service]
|
||||
Type=notify
|
||||
ExecStart=/usr/bin/Hyprland
|
||||
ExecStop=/usr/bin/hyprctl dispatch exit
|
||||
Restart=on-failure
|
||||
Slice=session.slice
|
5
example/hyprland-systemd.desktop
Normal file
@@ -0,0 +1,5 @@
|
||||
[Desktop Entry]
|
||||
Name=Hyprland
|
||||
Comment=An intelligent dynamic tiling Wayland compositor
|
||||
Exec=systemctl --user start --wait hyprland-session
|
||||
Type=Application
|
@@ -125,7 +125,7 @@ dwindle {
|
||||
|
||||
# See https://wiki.hyprland.org/Configuring/Master-Layout/ for more
|
||||
master {
|
||||
new_is_master = true
|
||||
new_status = master
|
||||
}
|
||||
|
||||
# https://wiki.hyprland.org/Configuring/Variables/#misc
|
||||
@@ -169,9 +169,9 @@ device {
|
||||
}
|
||||
|
||||
|
||||
####################
|
||||
### KEYBINDINGSS ###
|
||||
####################
|
||||
###################
|
||||
### KEYBINDINGS ###
|
||||
###################
|
||||
|
||||
# See https://wiki.hyprland.org/Configuring/Keywords/
|
||||
$mainMod = SUPER # Sets "Windows" key as main modifier
|
||||
@@ -228,6 +228,19 @@ bind = $mainMod, mouse_up, workspace, e-1
|
||||
bindm = $mainMod, mouse:272, movewindow
|
||||
bindm = $mainMod, mouse:273, resizewindow
|
||||
|
||||
# Laptop multimedia keys for volume and LCD brightness
|
||||
bindel = ,XF86AudioRaiseVolume, exec, wpctl set-volume -l 1 @DEFAULT_AUDIO_SINK@ 5%+
|
||||
bindel = ,XF86AudioLowerVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%-
|
||||
bindel = ,XF86AudioMute, exec, wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle
|
||||
bindel = ,XF86AudioMicMute, exec, wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle
|
||||
bindel = ,XF86MonBrightnessUp, exec, brightnessctl s 10%+
|
||||
bindel = ,XF86MonBrightnessDown, exec, brightnessctl s 10%-
|
||||
|
||||
# Requires playerctl
|
||||
bindl = , XF86AudioNext, exec, playerctl next
|
||||
bindl = , XF86AudioPause, exec, playerctl play-pause
|
||||
bindl = , XF86AudioPlay, exec, playerctl play-pause
|
||||
bindl = , XF86AudioPrev, exec, playerctl previous
|
||||
|
||||
##############################
|
||||
### WINDOWS AND WORKSPACES ###
|
||||
@@ -242,4 +255,8 @@ bindm = $mainMod, mouse:273, resizewindow
|
||||
# Example windowrule v2
|
||||
# windowrulev2 = float,class:^(kitty)$,title:^(kitty)$
|
||||
|
||||
windowrulev2 = suppressevent maximize, class:.* # You'll probably like this.
|
||||
# Ignore maximize requests from apps. You'll probably like this.
|
||||
windowrulev2 = suppressevent maximize, class:.*
|
||||
|
||||
# Fix some dragging issues with XWayland
|
||||
windowrulev2 = nofocus,class:^$,title:^$,xwayland:1,floating:1,fullscreen:0,pinned:0
|
||||
|
@@ -1,2 +1,10 @@
|
||||
install_data('hyprland.conf', install_dir: join_paths(get_option('datadir'), 'hyprland'), install_tag: 'runtime')
|
||||
install_data('hyprland.desktop', install_dir: join_paths(get_option('datadir'), 'wayland-sessions'), install_tag: 'runtime')
|
||||
install_data(
|
||||
'hyprland.conf',
|
||||
install_dir: join_paths(get_option('datadir'), 'hypr'),
|
||||
install_tag: 'runtime',
|
||||
)
|
||||
install_data(
|
||||
'hyprland.desktop',
|
||||
install_dir: join_paths(get_option('datadir'), 'wayland-sessions'),
|
||||
install_tag: 'runtime',
|
||||
)
|
||||
|
125
flake.lock
generated
@@ -1,5 +1,34 @@
|
||||
{
|
||||
"nodes": {
|
||||
"aquamarine": {
|
||||
"inputs": {
|
||||
"hyprutils": [
|
||||
"hyprutils"
|
||||
],
|
||||
"hyprwayland-scanner": [
|
||||
"hyprwayland-scanner"
|
||||
],
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
],
|
||||
"systems": [
|
||||
"systems"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1727261104,
|
||||
"narHash": "sha256-rxDI7WrxIRV9it9mDCHcLa7xQykf1JloXnoXr5xQ8zI=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "aquamarine",
|
||||
"rev": "b82fdaff917582a9d568969e15e61b398c71e990",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "hyprwm",
|
||||
"repo": "aquamarine",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"hyprcursor": {
|
||||
"inputs": {
|
||||
"hyprlang": [
|
||||
@@ -13,11 +42,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1717181720,
|
||||
"narHash": "sha256-yv+QZWsusu/NWjydkxixHC2g+tIJ9v+xkE2EiVpJj6g=",
|
||||
"lastModified": 1727532803,
|
||||
"narHash": "sha256-ZaZ7h7PY8mQc4vtGmVqWLAq9CAO02gHMyNR5yY8zDmM=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "hyprcursor",
|
||||
"rev": "9e27a2c2ceb1e0b85bd55b0afefad196056fe87c",
|
||||
"rev": "b98726e431d4d3ed58bd58bee1047cdb81cec69f",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -27,6 +56,29 @@
|
||||
}
|
||||
},
|
||||
"hyprland-protocols": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
],
|
||||
"systems": [
|
||||
"systems"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1727451107,
|
||||
"narHash": "sha256-qV9savtHwmZUa0eJE294WYJjKPGB2+bJhwByFShsVyo=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "hyprland-protocols",
|
||||
"rev": "6b3261ee13a6d2b99de79a31d352f6996e35bde3",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "hyprwm",
|
||||
"repo": "hyprland-protocols",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"hyprland-protocols_2": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"xdph",
|
||||
@@ -38,11 +90,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1691753796,
|
||||
"narHash": "sha256-zOEwiWoXk3j3+EoF3ySUJmberFewWlagvewDRuWYAso=",
|
||||
"lastModified": 1721326555,
|
||||
"narHash": "sha256-zCu4R0CSHEactW9JqYki26gy8h9f6rHmSwj4XJmlHgg=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "hyprland-protocols",
|
||||
"rev": "0c2ce70625cb30aef199cb388f99e19a61a6ce03",
|
||||
"rev": "5a11232266bf1a1f5952d5b179c3f4b2facaaa84",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -53,6 +105,9 @@
|
||||
},
|
||||
"hyprlang": {
|
||||
"inputs": {
|
||||
"hyprutils": [
|
||||
"hyprutils"
|
||||
],
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
],
|
||||
@@ -61,11 +116,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1716473782,
|
||||
"narHash": "sha256-+qLn4lsHU6iL3+HTo1gTQ1tWzet8K9h+IfVemzEQZj8=",
|
||||
"lastModified": 1725997860,
|
||||
"narHash": "sha256-d/rZ/fHR5l1n7PeyLw0StWMNLXVU9c4HFyfskw568so=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "hyprlang",
|
||||
"rev": "87d5d984109c839482b88b4795db073eb9ed446f",
|
||||
"rev": "dfeb5811dd6485490cce18d6cc1e38a055eea876",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -74,6 +129,29 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"hyprutils": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
],
|
||||
"systems": [
|
||||
"systems"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1727300645,
|
||||
"narHash": "sha256-OvAtVLaSRPnbXzOwlR1fVqCXR7i+ICRX3aPMCdIiv+c=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "hyprutils",
|
||||
"rev": "3f5293432b6dc6a99f26aca2eba3876d2660665c",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "hyprwm",
|
||||
"repo": "hyprutils",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"hyprwayland-scanner": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
@@ -84,11 +162,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1717784906,
|
||||
"narHash": "sha256-YxmfxHfWed1fosaa7fC1u7XoKp1anEZU+7Lh/ojRKoM=",
|
||||
"lastModified": 1726874836,
|
||||
"narHash": "sha256-VKR0sf0PSNCB0wPHVKSAn41mCNVCnegWmgkrneKDhHM=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "hyprwayland-scanner",
|
||||
"rev": "0f30f9eca6e404130988554accbb64d1c9ec877d",
|
||||
"rev": "500c81a9e1a76760371049a8d99e008ea77aa59e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -99,11 +177,11 @@
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1717602782,
|
||||
"narHash": "sha256-pL9jeus5QpX5R+9rsp3hhZ+uplVHscNJh8n8VpqscM0=",
|
||||
"lastModified": 1727348695,
|
||||
"narHash": "sha256-J+PeFKSDV+pHL7ukkfpVzCOO7mBSrrpJ3svwBFABbhI=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "e8057b67ebf307f01bdcc8fba94d94f75039d1f6",
|
||||
"rev": "1925c603f17fc89f4c8f6bf6f631a802ad85d784",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -115,8 +193,11 @@
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"aquamarine": "aquamarine",
|
||||
"hyprcursor": "hyprcursor",
|
||||
"hyprland-protocols": "hyprland-protocols",
|
||||
"hyprlang": "hyprlang",
|
||||
"hyprutils": "hyprutils",
|
||||
"hyprwayland-scanner": "hyprwayland-scanner",
|
||||
"nixpkgs": "nixpkgs",
|
||||
"systems": "systems",
|
||||
@@ -140,10 +221,16 @@
|
||||
},
|
||||
"xdph": {
|
||||
"inputs": {
|
||||
"hyprland-protocols": "hyprland-protocols",
|
||||
"hyprland-protocols": "hyprland-protocols_2",
|
||||
"hyprlang": [
|
||||
"hyprlang"
|
||||
],
|
||||
"hyprutils": [
|
||||
"hyprutils"
|
||||
],
|
||||
"hyprwayland-scanner": [
|
||||
"hyprwayland-scanner"
|
||||
],
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
],
|
||||
@@ -152,11 +239,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1716290197,
|
||||
"narHash": "sha256-1u9Exrc7yx9qtES2brDh7/DDZ8w8ap1nboIOAtCgeuM=",
|
||||
"lastModified": 1727524473,
|
||||
"narHash": "sha256-1DGktDtSWIJpnDbVoj/qpvJSH5zg6JbOfuh6xqZMap0=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "xdg-desktop-portal-hyprland",
|
||||
"rev": "91e48d6acd8a5a611d26f925e51559ab743bc438",
|
||||
"rev": "7e500e679ede40e79cf2d89b5f5fa3e34923bd26",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
37
flake.nix
@@ -7,6 +7,14 @@
|
||||
# <https://github.com/nix-systems/nix-systems>
|
||||
systems.url = "github:nix-systems/default-linux";
|
||||
|
||||
aquamarine = {
|
||||
url = "github:hyprwm/aquamarine";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
inputs.systems.follows = "systems";
|
||||
inputs.hyprutils.follows = "hyprutils";
|
||||
inputs.hyprwayland-scanner.follows = "hyprwayland-scanner";
|
||||
};
|
||||
|
||||
hyprcursor = {
|
||||
url = "github:hyprwm/hyprcursor";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
@@ -14,10 +22,23 @@
|
||||
inputs.hyprlang.follows = "hyprlang";
|
||||
};
|
||||
|
||||
hyprland-protocols = {
|
||||
url = "github:hyprwm/hyprland-protocols";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
inputs.systems.follows = "systems";
|
||||
};
|
||||
|
||||
hyprlang = {
|
||||
url = "github:hyprwm/hyprlang";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
inputs.systems.follows = "systems";
|
||||
inputs.hyprutils.follows = "hyprutils";
|
||||
};
|
||||
|
||||
hyprutils = {
|
||||
url = "github:hyprwm/hyprutils";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
inputs.systems.follows = "systems";
|
||||
};
|
||||
|
||||
hyprwayland-scanner = {
|
||||
@@ -31,6 +52,8 @@
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
inputs.systems.follows = "systems";
|
||||
inputs.hyprlang.follows = "hyprlang";
|
||||
inputs.hyprutils.follows = "hyprutils";
|
||||
inputs.hyprwayland-scanner.follows = "hyprwayland-scanner";
|
||||
};
|
||||
};
|
||||
|
||||
@@ -50,6 +73,15 @@
|
||||
hyprland-extras
|
||||
];
|
||||
});
|
||||
pkgsCrossFor = eachSystem (system: crossSystem:
|
||||
import nixpkgs {
|
||||
localSystem = system;
|
||||
crossSystem = crossSystem;
|
||||
overlays = with self.overlays; [
|
||||
hyprland-packages
|
||||
hyprland-extras
|
||||
];
|
||||
});
|
||||
in {
|
||||
overlays = import ./nix/overlays.nix {inherit self lib inputs;};
|
||||
|
||||
@@ -75,17 +107,18 @@
|
||||
|
||||
xdg-desktop-portal-hyprland
|
||||
;
|
||||
hyprland-cross = (pkgsCrossFor.${system} "aarch64-linux").hyprland;
|
||||
});
|
||||
|
||||
devShells = eachSystem (system: {
|
||||
default =
|
||||
pkgsFor.${system}.mkShell.override {
|
||||
stdenv = pkgsFor.${system}.gcc13Stdenv;
|
||||
inherit (self.packages.${system}.default) stdenv;
|
||||
} {
|
||||
name = "hyprland-shell";
|
||||
nativeBuildInputs = with pkgsFor.${system}; [expat libxml2];
|
||||
hardeningDisable = ["fortify"];
|
||||
inputsFrom = [pkgsFor.${system}.hyprland];
|
||||
packages = [pkgsFor.${system}.clang-tools];
|
||||
};
|
||||
});
|
||||
|
||||
|
@@ -5,8 +5,12 @@ project(
|
||||
DESCRIPTION "Control utility for Hyprland"
|
||||
)
|
||||
|
||||
pkg_check_modules(deps REQUIRED IMPORTED_TARGET hyprutils>=0.1.1)
|
||||
|
||||
add_executable(hyprctl "main.cpp")
|
||||
|
||||
target_link_libraries(hyprctl PUBLIC PkgConfig::hyprctl_deps)
|
||||
|
||||
# binary
|
||||
install(TARGETS hyprctl)
|
||||
|
||||
|
@@ -1,4 +0,0 @@
|
||||
all:
|
||||
$(CXX) $(CXXFLAGS) -std=c++2b ./main.cpp -o ./hyprctl
|
||||
clean:
|
||||
rm ./hyprctl
|
@@ -38,7 +38,8 @@ commands:
|
||||
plugin ... → Issue a plugin request
|
||||
reload [config-only] → Issue a reload to force reload the config. Pass
|
||||
'config-only' to disable monitor reload
|
||||
rollinglog → Prints tail of the log
|
||||
rollinglog → Prints tail of the log. Also supports -f/--follow
|
||||
option
|
||||
setcursor <theme> <size> → Sets the cursor theme and reloads the cursor
|
||||
manager
|
||||
seterror <color> <message...> → Sets the hyprctl error string. Color has
|
||||
|
@@ -1,17 +1,17 @@
|
||||
_hyprctl_cmd_2 () {
|
||||
hyprctl monitors | grep Monitor | awk '{ print $2 }'
|
||||
_hyprctl_cmd_1 () {
|
||||
hyprctl monitors | awk '/Monitor/{ print $2 }'
|
||||
}
|
||||
|
||||
_hyprctl_cmd_3 () {
|
||||
hyprpm list | grep "Plugin" | awk '{print $4}'
|
||||
hyprctl clients | awk '/class/{print $2}'
|
||||
}
|
||||
|
||||
_hyprctl_cmd_2 () {
|
||||
hyprctl devices | sed -n '/Keyboard at/{n; s/^\s\+//; p}'
|
||||
}
|
||||
|
||||
_hyprctl_cmd_0 () {
|
||||
hyprctl clients | grep class | awk '{print $2}'
|
||||
}
|
||||
|
||||
_hyprctl_cmd_1 () {
|
||||
hyprctl devices | sed -n '/Keyboard at/{n; s/^\s\+//; p}'
|
||||
hyprpm list | awk '/Plugin/{print $4}'
|
||||
}
|
||||
|
||||
_hyprctl () {
|
||||
@@ -23,25 +23,25 @@ _hyprctl () {
|
||||
local words cword
|
||||
_get_comp_words_by_ref -n "$COMP_WORDBREAKS" words cword
|
||||
|
||||
local -a literals=("cyclenext" "globalshortcuts" "cursorpos" "bordersize" "renameworkspace" "animationstyle" "focuswindow" "0" "auto" "swapnext" "forceallowsinput" "moveactive" "activebordercolor" "alphafullscreen" "wayland" "layers" "minsize" "monitors" "1" "kill" "settiled" "3" "focusmonitor" "swapwindow" "moveoutofgroup" "notify" "movecursor" "setcursor" "seterror" "movecurrentworkspacetomonitor" "4" "nomaxsize" "forcenoanims" "setprop" "-i" "-q" "togglefloating" "workspacerules" "movetoworkspace" "disable" "setignoregrouplock" "workspaces" "movegroupwindow" "closewindow" "0" "--instance" "binds" "movewindow" "splitratio" "alpha" "denywindowfromgroup" "workspace" "configerrors" "togglegroup" "getoption" "forceopaque" "keepaspectratio" "killactive" "pass" "decorations" "devices" "focuscurrentorlast" "submap" "global" "alphafullscreenoverride" "forcerendererreload" "movewindowpixel" "headless" "version" "dpms" "resizeactive" "moveintogroup" "5" "alphaoverride" "setfloating" "rollinglog" "::=" "rounding" "layouts" "moveworkspacetomonitor" "exec" "alphainactiveoverride" "alterzorder" "fakefullscreen" "nofocus" "keyword" "forcenoborder" "forcenodim" "--quiet" "pin" "output" "forcenoblur" "togglespecialworkspace" "fullscreen" "toggleopaque" "focusworkspaceoncurrentmonitor" "next" "changegroupactive" "-j" "instances" "execr" "exit" "clients" "all" "--batch" "dismissnotify" "inactivebordercolor" "switchxkblayout" "movetoworkspacesilent" "tagwindow" "movewindoworgroup" "-r" "movefocus" "focusurgentorlast" "remove" "activeworkspace" "dispatch" "create" "centerwindow" "2" "hyprpaper" "-1" "reload" "alphainactive" "systeminfo" "plugin" "dimaround" "activewindow" "swapactiveworkspaces" "splash" "sendshortcut" "maxsize" "lockactivegroup" "windowdancecompat" "forceopaqueoverriden" "lockgroups" "movecursortocorner" "x11" "prev" "1" "resizewindowpixel" "forcenoshadow")
|
||||
|
||||
declare -a literals=(resizeactive 2 changegroupactive -r moveintogroup forceallowsinput 4 ::= systeminfo all layouts setprop animationstyle switchxkblayout create denywindowfromgroup headless activebordercolor exec setcursor wayland focusurgentorlast workspacerules movecurrentworkspacetomonitor movetoworkspacesilent hyprpaper alpha inactivebordercolor movegroupwindow movecursortocorner movewindowpixel prev movewindow globalshortcuts clients dimaround setignoregrouplock splash execr monitors 0 forcenoborder -q animations 1 nomaxsize splitratio moveactive pass swapnext devices layers rounding lockactivegroup 5 moveworkspacetomonitor -f -i --quiet forcenodim pin 0 1 forceopaque forcenoshadow setfloating minsize alphaoverride sendshortcut workspaces cyclenext alterzorder togglegroup lockgroups bordersize dpms focuscurrentorlast -1 --batch notify remove instances 1 3 moveoutofgroup killactive 2 movetoworkspace movecursor configerrors closewindow swapwindow tagwindow forcerendererreload centerwindow auto focuswindow seterror nofocus alphafullscreen binds version -h togglespecialworkspace fullscreen windowdancecompat 0 keyword toggleopaque 3 --instance togglefloating renameworkspace alphafullscreenoverride activeworkspace x11 kill forceopaqueoverriden output global dispatch reload forcenoblur -j event --help disable -1 activewindow keepaspectratio dismissnotify focusmonitor movefocus plugin exit workspace fullscreenstate getoption alphainactiveoverride alphainactive decorations settiled config-only descriptions resizewindowpixel fakefullscreen rollinglog swapactiveworkspaces submap next movewindoworgroup cursorpos forcenoanims focusworkspaceoncurrentmonitor maxsize)
|
||||
declare -A literal_transitions
|
||||
literal_transitions[0]="([105]=1 [75]=2 [33]=3 [35]=4 [1]=2 [2]=2 [78]=2 [107]=5 [37]=2 [111]=4 [41]=2 [46]=2 [115]=2 [85]=6 [116]=8 [52]=2 [88]=4 [54]=2 [90]=9 [120]=2 [122]=2 [124]=2 [15]=2 [59]=10 [60]=2 [17]=11 [125]=12 [19]=2 [127]=2 [129]=2 [25]=13 [68]=2 [98]=4 [99]=2 [27]=2 [28]=14 [102]=2 [104]=4)"
|
||||
literal_transitions[3]="([73]=17 [13]=2 [32]=17 [55]=17 [56]=17 [91]=17 [106]=2 [123]=2 [77]=1 [16]=2 [126]=17 [3]=1 [5]=2 [64]=17 [131]=2 [133]=17 [81]=17 [134]=17 [84]=17 [31]=17 [49]=2 [12]=2 [86]=17 [10]=17 [87]=17 [141]=17)"
|
||||
literal_transitions[7]="([105]=1 [75]=2 [33]=3 [1]=2 [2]=2 [78]=2 [107]=5 [37]=2 [41]=2 [46]=2 [115]=2 [85]=6 [116]=8 [52]=2 [54]=2 [90]=9 [120]=2 [122]=2 [124]=2 [15]=2 [59]=10 [60]=2 [17]=11 [125]=12 [19]=2 [127]=2 [129]=2 [25]=13 [68]=2 [99]=2 [27]=2 [28]=14 [102]=2)"
|
||||
literal_transitions[8]="([101]=2 [130]=2 [132]=2 [0]=2 [74]=2 [36]=2 [108]=2 [109]=2 [38]=2 [110]=2 [4]=2 [79]=2 [40]=2 [80]=2 [113]=2 [6]=2 [42]=2 [43]=2 [82]=2 [83]=2 [47]=2 [48]=2 [9]=2 [50]=2 [51]=2 [53]=2 [11]=2 [112]=2 [89]=2 [118]=2 [57]=2 [92]=2 [58]=2 [93]=2 [94]=2 [61]=2 [62]=2 [128]=2 [95]=2 [63]=2 [20]=2 [97]=2 [22]=2 [23]=2 [65]=2 [66]=2 [135]=2 [136]=2 [24]=2 [26]=2 [69]=2 [100]=2 [70]=2 [140]=2 [29]=2 [71]=2)"
|
||||
literal_transitions[9]="([117]=20 [114]=16)"
|
||||
literal_transitions[11]="([103]=2)"
|
||||
literal_transitions[13]="([21]=1 [119]=1 [30]=1 [139]=1 [121]=1 [44]=1 [72]=1)"
|
||||
literal_transitions[14]="([39]=2)"
|
||||
literal_transitions[15]="([138]=2 [96]=2)"
|
||||
literal_transitions[17]="([18]=2 [7]=2)"
|
||||
literal_transitions[18]="([76]=19)"
|
||||
literal_transitions[19]="([34]=4 [45]=4)"
|
||||
literal_transitions[20]="([8]=2 [67]=2 [14]=2 [137]=2)"
|
||||
|
||||
declare -A match_anything_transitions
|
||||
match_anything_transitions=([1]=2 [0]=7 [6]=2 [15]=2 [10]=2 [5]=15 [14]=18 [7]=7 [2]=18 [16]=2 [12]=2 [11]=18)
|
||||
literal_transitions[0]="([120]=14 [43]=2 [125]=21 [81]=2 [3]=21 [51]=2 [50]=2 [128]=2 [89]=2 [58]=21 [8]=2 [10]=2 [11]=3 [130]=4 [13]=5 [97]=6 [101]=2 [102]=21 [133]=7 [100]=2 [137]=2 [22]=2 [19]=2 [140]=8 [25]=2 [143]=2 [107]=9 [146]=10 [69]=2 [33]=2 [34]=2 [78]=21 [114]=2 [37]=2 [151]=2 [116]=2 [121]=13 [123]=21 [39]=11 [42]=21 [79]=15 [118]=12)"
|
||||
literal_transitions[1]="([81]=2 [51]=2 [50]=2 [128]=2 [8]=2 [89]=2 [10]=2 [11]=3 [130]=4 [13]=5 [97]=6 [101]=2 [133]=7 [100]=2 [22]=2 [19]=2 [137]=2 [140]=8 [25]=2 [143]=2 [107]=9 [146]=10 [69]=2 [33]=2 [34]=2 [114]=2 [37]=2 [151]=2 [116]=2 [39]=11 [118]=12 [121]=13 [120]=14 [79]=15 [43]=2)"
|
||||
literal_transitions[3]="([139]=2 [63]=16 [64]=16 [45]=16 [105]=16 [27]=2 [26]=2 [52]=4 [5]=16 [66]=2 [67]=16 [129]=16 [113]=16 [12]=2 [74]=4 [99]=2 [35]=16 [152]=16 [98]=16 [59]=16 [117]=16 [41]=16 [17]=2 [138]=16 [154]=2 [122]=16)"
|
||||
literal_transitions[6]="([126]=2)"
|
||||
literal_transitions[10]="([56]=2)"
|
||||
literal_transitions[11]="([9]=2)"
|
||||
literal_transitions[12]="([14]=19 [80]=22)"
|
||||
literal_transitions[13]="([142]=2)"
|
||||
literal_transitions[14]="([0]=2 [84]=2 [2]=2 [85]=2 [4]=2 [87]=2 [88]=2 [90]=2 [91]=2 [92]=2 [93]=2 [94]=2 [96]=2 [15]=2 [18]=2 [103]=2 [21]=2 [104]=2 [23]=2 [24]=2 [28]=2 [29]=2 [30]=2 [108]=2 [111]=2 [32]=2 [112]=2 [36]=2 [38]=2 [119]=2 [124]=2 [46]=2 [47]=2 [48]=2 [49]=2 [53]=2 [55]=2 [131]=2 [132]=2 [134]=2 [135]=2 [60]=2 [136]=20 [141]=2 [65]=2 [144]=2 [145]=2 [68]=2 [147]=2 [70]=2 [71]=2 [72]=2 [73]=2 [148]=2 [75]=2 [76]=2 [150]=2 [153]=2)"
|
||||
literal_transitions[15]="([86]=4 [6]=4 [109]=4 [61]=4 [77]=4 [54]=4 [62]=4)"
|
||||
literal_transitions[16]="([40]=2 [44]=2)"
|
||||
literal_transitions[17]="([7]=23)"
|
||||
literal_transitions[18]="([31]=2 [149]=2)"
|
||||
literal_transitions[19]="([95]=2 [16]=2 [115]=2 [20]=2)"
|
||||
literal_transitions[20]="([106]=2 [82]=2 [127]=2 [1]=2 [83]=2)"
|
||||
literal_transitions[23]="([57]=21 [110]=21)"
|
||||
declare -A match_anything_transitions=([6]=17 [7]=2 [0]=1 [22]=2 [5]=18 [4]=2 [2]=17 [18]=2 [11]=17 [8]=2 [9]=2 [13]=17 [10]=17 [1]=1)
|
||||
declare -A subword_transitions
|
||||
|
||||
local state=0
|
||||
@@ -79,21 +79,9 @@ _hyprctl () {
|
||||
done
|
||||
|
||||
|
||||
local -a matches=()
|
||||
|
||||
local prefix="${words[$cword]}"
|
||||
|
||||
local shortest_suffix="$word"
|
||||
for ((i=0; i < ${#COMP_WORDBREAKS}; i++)); do
|
||||
local char="${COMP_WORDBREAKS:$i:1}"
|
||||
local candidate="${word##*$char}"
|
||||
if [[ ${#candidate} -lt ${#shortest_suffix} ]]; then
|
||||
shortest_suffix=$candidate
|
||||
fi
|
||||
done
|
||||
local superfluous_prefix=""
|
||||
if [[ "$shortest_suffix" != "$word" ]]; then
|
||||
local superfluous_prefix=${word%$shortest_suffix}
|
||||
fi
|
||||
|
||||
if [[ -v "literal_transitions[$state]" ]]; then
|
||||
local state_transitions_initializer=${literal_transitions[$state]}
|
||||
declare -A state_transitions
|
||||
@@ -102,25 +90,38 @@ _hyprctl () {
|
||||
for literal_id in "${!state_transitions[@]}"; do
|
||||
local literal="${literals[$literal_id]}"
|
||||
if [[ $literal = "${prefix}"* ]]; then
|
||||
local completion=${literal#"$superfluous_prefix"}
|
||||
COMPREPLY+=("$completion ")
|
||||
matches+=("$literal ")
|
||||
fi
|
||||
done
|
||||
fi
|
||||
declare -A commands
|
||||
commands=([5]=1 [16]=2 [12]=3 [10]=0)
|
||||
commands=([7]=0 [22]=1 [8]=3 [5]=2)
|
||||
if [[ -v "commands[$state]" ]]; then
|
||||
local command_id=${commands[$state]}
|
||||
local completions=()
|
||||
mapfile -t completions < <(_hyprctl_cmd_${command_id} "$prefix" | cut -f1)
|
||||
readarray -t completions < <(_hyprctl_cmd_${command_id} "$prefix" | cut -f1)
|
||||
for item in "${completions[@]}"; do
|
||||
if [[ $item = "${prefix}"* ]]; then
|
||||
COMPREPLY+=("$item")
|
||||
matches+=("$item")
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
|
||||
local shortest_suffix="$prefix"
|
||||
for ((i=0; i < ${#COMP_WORDBREAKS}; i++)); do
|
||||
local char="${COMP_WORDBREAKS:$i:1}"
|
||||
local candidate=${prefix##*$char}
|
||||
if [[ ${#candidate} -lt ${#shortest_suffix} ]]; then
|
||||
shortest_suffix=$candidate
|
||||
fi
|
||||
done
|
||||
local superfluous_prefix=""
|
||||
if [[ "$shortest_suffix" != "$prefix" ]]; then
|
||||
local superfluous_prefix=${prefix%$shortest_suffix}
|
||||
fi
|
||||
COMPREPLY=("${matches[@]#$superfluous_prefix}")
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
|
@@ -1,21 +1,21 @@
|
||||
function _hyprctl_3
|
||||
function _hyprctl_2
|
||||
set 1 $argv[1]
|
||||
hyprctl monitors | grep Monitor | awk '{ print $2 }'
|
||||
hyprctl monitors | awk '/Monitor/{ print $2 }'
|
||||
end
|
||||
|
||||
function _hyprctl_4
|
||||
set 1 $argv[1]
|
||||
hyprpm list | grep "Plugin" | awk '{print $4}'
|
||||
hyprctl clients | awk '/class/{print $2}'
|
||||
end
|
||||
|
||||
function _hyprctl_3
|
||||
set 1 $argv[1]
|
||||
hyprctl devices | sed -n '/Keyboard at/{n; s/^\s\+//; p}'
|
||||
end
|
||||
|
||||
function _hyprctl_1
|
||||
set 1 $argv[1]
|
||||
hyprctl clients | grep class | awk '{print $2}'
|
||||
end
|
||||
|
||||
function _hyprctl_2
|
||||
set 1 $argv[1]
|
||||
hyprctl devices | sed -n '/Keyboard at/{n; s/^\s\+//; p}'
|
||||
hyprpm list | awk '/Plugin/{print $4}'
|
||||
end
|
||||
|
||||
function _hyprctl
|
||||
@@ -29,145 +29,160 @@ function _hyprctl
|
||||
set COMP_CWORD (count $COMP_WORDS)
|
||||
end
|
||||
|
||||
set --local literals "cyclenext" "globalshortcuts" "cursorpos" "bordersize" "renameworkspace" "animationstyle" "focuswindow" "0" "auto" "swapnext" "forceallowsinput" "moveactive" "activebordercolor" "alphafullscreen" "wayland" "layers" "minsize" "monitors" "1" "kill" "settiled" "3" "focusmonitor" "swapwindow" "moveoutofgroup" "notify" "movecursor" "setcursor" "seterror" "movecurrentworkspacetomonitor" "4" "nomaxsize" "forcenoanims" "setprop" "-i" "-q" "togglefloating" "workspacerules" "movetoworkspace" "disable" "setignoregrouplock" "workspaces" "movegroupwindow" "closewindow" "0" "--instance" "binds" "movewindow" "splitratio" "alpha" "denywindowfromgroup" "workspace" "configerrors" "togglegroup" "getoption" "forceopaque" "keepaspectratio" "killactive" "pass" "decorations" "devices" "focuscurrentorlast" "submap" "global" "alphafullscreenoverride" "forcerendererreload" "movewindowpixel" "headless" "version" "dpms" "resizeactive" "moveintogroup" "5" "alphaoverride" "setfloating" "rollinglog" "::=" "rounding" "layouts" "moveworkspacetomonitor" "exec" "alphainactiveoverride" "alterzorder" "fakefullscreen" "nofocus" "keyword" "forcenoborder" "forcenodim" "--quiet" "pin" "output" "forcenoblur" "togglespecialworkspace" "fullscreen" "toggleopaque" "focusworkspaceoncurrentmonitor" "next" "changegroupactive" "-j" "instances" "execr" "exit" "clients" "all" "--batch" "dismissnotify" "inactivebordercolor" "switchxkblayout" "movetoworkspacesilent" "tagwindow" "movewindoworgroup" "-r" "movefocus" "focusurgentorlast" "remove" "activeworkspace" "dispatch" "create" "centerwindow" "2" "hyprpaper" "-1" "reload" "alphainactive" "systeminfo" "plugin" "dimaround" "activewindow" "swapactiveworkspaces" "splash" "sendshortcut" "maxsize" "lockactivegroup" "windowdancecompat" "forceopaqueoverriden" "lockgroups" "movecursortocorner" "x11" "prev" "1" "resizewindowpixel" "forcenoshadow"
|
||||
set literals "resizeactive" "2" "changegroupactive" "-r" "moveintogroup" "forceallowsinput" "4" "::=" "systeminfo" "all" "layouts" "setprop" "animationstyle" "switchxkblayout" "create" "denywindowfromgroup" "headless" "activebordercolor" "exec" "setcursor" "wayland" "focusurgentorlast" "workspacerules" "movecurrentworkspacetomonitor" "movetoworkspacesilent" "hyprpaper" "alpha" "inactivebordercolor" "movegroupwindow" "movecursortocorner" "movewindowpixel" "prev" "movewindow" "globalshortcuts" "clients" "dimaround" "setignoregrouplock" "splash" "execr" "monitors" "0" "forcenoborder" "-q" "animations" "1" "nomaxsize" "splitratio" "moveactive" "pass" "swapnext" "devices" "layers" "rounding" "lockactivegroup" "5" "moveworkspacetomonitor" "-f" "-i" "--quiet" "forcenodim" "pin" "0" "1" "forceopaque" "forcenoshadow" "setfloating" "minsize" "alphaoverride" "sendshortcut" "workspaces" "cyclenext" "alterzorder" "togglegroup" "lockgroups" "bordersize" "dpms" "focuscurrentorlast" "-1" "--batch" "notify" "remove" "instances" "1" "3" "moveoutofgroup" "killactive" "2" "movetoworkspace" "movecursor" "configerrors" "closewindow" "swapwindow" "tagwindow" "forcerendererreload" "centerwindow" "auto" "focuswindow" "seterror" "nofocus" "alphafullscreen" "binds" "version" "-h" "togglespecialworkspace" "fullscreen" "windowdancecompat" "0" "keyword" "toggleopaque" "3" "--instance" "togglefloating" "renameworkspace" "alphafullscreenoverride" "activeworkspace" "x11" "kill" "forceopaqueoverriden" "output" "global" "dispatch" "reload" "forcenoblur" "-j" "event" "--help" "disable" "-1" "activewindow" "keepaspectratio" "dismissnotify" "focusmonitor" "movefocus" "plugin" "exit" "workspace" "fullscreenstate" "getoption" "alphainactiveoverride" "alphainactive" "decorations" "settiled" "config-only" "descriptions" "resizewindowpixel" "fakefullscreen" "rollinglog" "swapactiveworkspaces" "submap" "next" "movewindoworgroup" "cursorpos" "forcenoanims" "focusworkspaceoncurrentmonitor" "maxsize"
|
||||
|
||||
set --local descriptions
|
||||
set descriptions[1] "Focus the next window on a workspace"
|
||||
set descriptions[3] "Get the current cursor pos in global layout coordinates"
|
||||
set descriptions[5] "Rename a workspace"
|
||||
set descriptions[7] "Focus the first window matching"
|
||||
set descriptions[10] "Swap the focused window with the next window"
|
||||
set descriptions[12] "Move the active window"
|
||||
set descriptions[16] "List the layers"
|
||||
set descriptions[18] "List active outputs with their properties"
|
||||
set descriptions[20] "Get into a kill mode, where you can kill an app by clicking on it"
|
||||
set descriptions[21] "Set the current window's floating state to false"
|
||||
set descriptions[22] "ERROR"
|
||||
set descriptions[23] "Focus a monitor"
|
||||
set descriptions[24] "Swap the active window with another window"
|
||||
set descriptions[25] "Move the active window out of a group"
|
||||
set descriptions[26] "Send a notification using the built-in Hyprland notification system"
|
||||
set descriptions[27] "Move the cursor to a specified position"
|
||||
set descriptions[28] "Set the cursor theme and reloads the cursor manager"
|
||||
set descriptions[29] "Set the hyprctl error string"
|
||||
set descriptions[30] "Move the active workspace to a monitor"
|
||||
set descriptions[31] "CONFUSED"
|
||||
set descriptions[34] "Set a property of a window"
|
||||
set descriptions[35] "Specify the Hyprland instance"
|
||||
set descriptions[36] "Disable output"
|
||||
set descriptions[37] "Toggle the current window's floating state"
|
||||
set descriptions[38] "Get the list of defined workspace rules"
|
||||
set descriptions[39] "Move the focused window to a workspace"
|
||||
set descriptions[41] "Temporarily enable or disable binds:ignore_group_lock"
|
||||
set descriptions[42] "List all workspaces with their properties"
|
||||
set descriptions[43] "Swap the active window with the next or previous in a group"
|
||||
set descriptions[44] "Close a specified window"
|
||||
set descriptions[45] "WARNING"
|
||||
set descriptions[46] "Specify the Hyprland instance"
|
||||
set descriptions[47] "List all registered binds"
|
||||
set descriptions[48] "Move the active window in a direction or to a monitor"
|
||||
set descriptions[49] "Change the split ratio"
|
||||
set descriptions[51] "Prohibit the active window from becoming or being inserted into group"
|
||||
set descriptions[52] "Change the workspace"
|
||||
set descriptions[53] "List all current config parsing errors"
|
||||
set descriptions[54] "Toggle the current active window into a group"
|
||||
set descriptions[55] "Get the config option status (values)"
|
||||
set descriptions[58] "Close the active window"
|
||||
set descriptions[59] "Pass the key to a specified window"
|
||||
set descriptions[60] "List all decorations and their info"
|
||||
set descriptions[61] "List all connected keyboards and mice"
|
||||
set descriptions[62] "Switch focus from current to previously focused window"
|
||||
set descriptions[63] "Change the current mapping group"
|
||||
set descriptions[64] "Execute a Global Shortcut using the GlobalShortcuts portal"
|
||||
set descriptions[66] "Force the renderer to reload all resources and outputs"
|
||||
set descriptions[67] "Move a selected window"
|
||||
set descriptions[69] "Print the Hyprland version: flags, commit and branch of build"
|
||||
set descriptions[70] "Set all monitors' DPMS status"
|
||||
set descriptions[71] "Resize the active window"
|
||||
set descriptions[72] "Move the active window into a group"
|
||||
set descriptions[73] "OK"
|
||||
set descriptions[75] "Set the current window's floating state to true"
|
||||
set descriptions[76] "Print tail of the log"
|
||||
set descriptions[79] "List all layouts available (including plugin ones)"
|
||||
set descriptions[80] "Move a workspace to a monitor"
|
||||
set descriptions[81] "Execute a shell command"
|
||||
set descriptions[83] "Modify the window stack order of the active or specified window"
|
||||
set descriptions[84] "Toggle the focused window's internal fullscreen state"
|
||||
set descriptions[86] "Issue a keyword to call a config keyword dynamically"
|
||||
set descriptions[89] "Disable output"
|
||||
set descriptions[90] "Pin a window"
|
||||
set descriptions[91] "Allows adding/removing fake outputs to a specific backend"
|
||||
set descriptions[93] "Toggle a special workspace on/off"
|
||||
set descriptions[94] "Toggle the focused window's fullscreen state"
|
||||
set descriptions[95] "Toggle the current window to always be opaque"
|
||||
set descriptions[96] "Focus the requested workspace"
|
||||
set descriptions[98] "Switch to the next window in a group"
|
||||
set descriptions[99] "Output in JSON format"
|
||||
set descriptions[100] "List all running Hyprland instances and their info"
|
||||
set descriptions[101] "Execute a raw shell command"
|
||||
set descriptions[102] "Exit the compositor with no questions asked"
|
||||
set descriptions[103] "List all windows with their properties"
|
||||
set descriptions[105] "Execute a batch of commands separated by ;"
|
||||
set descriptions[106] "Dismiss all or up to amount of notifications"
|
||||
set descriptions[108] "Set the xkb layout index for a keyboard"
|
||||
set descriptions[109] "Move window doesnt switch to the workspace"
|
||||
set descriptions[110] "Apply a tag to the window"
|
||||
set descriptions[111] "Behave as moveintogroup"
|
||||
set descriptions[112] "Refresh state after issuing the command"
|
||||
set descriptions[113] "Move the focus in a direction"
|
||||
set descriptions[114] "Focus the urgent window or the last window"
|
||||
set descriptions[116] "Get the active workspace name and its properties"
|
||||
set descriptions[117] "Issue a dispatch to call a keybind dispatcher with an arg"
|
||||
set descriptions[119] "Center the active window"
|
||||
set descriptions[120] "HINT"
|
||||
set descriptions[121] "Interact with hyprpaper if present"
|
||||
set descriptions[122] "No Icon"
|
||||
set descriptions[123] "Force reload the config"
|
||||
set descriptions[125] "Print system info"
|
||||
set descriptions[126] "Interact with a plugin"
|
||||
set descriptions[128] "Get the active window name and its properties"
|
||||
set descriptions[129] "Swap the active workspaces between two monitors"
|
||||
set descriptions[130] "Print the current random splash"
|
||||
set descriptions[131] "On shortcut X sends shortcut Y to a specified window"
|
||||
set descriptions[133] "Lock the focused group"
|
||||
set descriptions[136] "Lock the groups"
|
||||
set descriptions[137] "Move the cursor to the corner of the active window"
|
||||
set descriptions[140] "INFO"
|
||||
set descriptions[141] "Resize a selected window"
|
||||
set descriptions
|
||||
set descriptions[1] "Resize the active window"
|
||||
set descriptions[2] "Fullscreen"
|
||||
set descriptions[3] "Switch to the next window in a group"
|
||||
set descriptions[4] "Refresh state after issuing the command"
|
||||
set descriptions[5] "Move the active window into a group"
|
||||
set descriptions[7] "CONFUSED"
|
||||
set descriptions[9] "Print system info"
|
||||
set descriptions[11] "List all layouts available (including plugin ones)"
|
||||
set descriptions[12] "Set a property of a window"
|
||||
set descriptions[14] "Set the xkb layout index for a keyboard"
|
||||
set descriptions[16] "Prohibit the active window from becoming or being inserted into group"
|
||||
set descriptions[19] "Execute a shell command"
|
||||
set descriptions[20] "Set the cursor theme and reloads the cursor manager"
|
||||
set descriptions[22] "Focus the urgent window or the last window"
|
||||
set descriptions[23] "Get the list of defined workspace rules"
|
||||
set descriptions[24] "Move the active workspace to a monitor"
|
||||
set descriptions[25] "Move window doesnt switch to the workspace"
|
||||
set descriptions[26] "Interact with hyprpaper if present"
|
||||
set descriptions[29] "Swap the active window with the next or previous in a group"
|
||||
set descriptions[30] "Move the cursor to the corner of the active window"
|
||||
set descriptions[31] "Move a selected window"
|
||||
set descriptions[33] "Move the active window in a direction or to a monitor"
|
||||
set descriptions[34] "Lists all global shortcuts"
|
||||
set descriptions[35] "List all windows with their properties"
|
||||
set descriptions[37] "Temporarily enable or disable binds:ignore_group_lock"
|
||||
set descriptions[38] "Print the current random splash"
|
||||
set descriptions[39] "Execute a raw shell command"
|
||||
set descriptions[40] "List active outputs with their properties"
|
||||
set descriptions[43] "Disable output"
|
||||
set descriptions[44] "Gets the current config info about animations and beziers"
|
||||
set descriptions[47] "Change the split ratio"
|
||||
set descriptions[48] "Move the active window"
|
||||
set descriptions[49] "Pass the key to a specified window"
|
||||
set descriptions[50] "Swap the focused window with the next window"
|
||||
set descriptions[51] "List all connected keyboards and mice"
|
||||
set descriptions[52] "List the layers"
|
||||
set descriptions[54] "Lock the focused group"
|
||||
set descriptions[55] "OK"
|
||||
set descriptions[56] "Move a workspace to a monitor"
|
||||
set descriptions[58] "Specify the Hyprland instance"
|
||||
set descriptions[59] "Disable output"
|
||||
set descriptions[61] "Pin a window"
|
||||
set descriptions[62] "WARNING"
|
||||
set descriptions[63] "INFO"
|
||||
set descriptions[66] "Set the current window's floating state to true"
|
||||
set descriptions[69] "On shortcut X sends shortcut Y to a specified window"
|
||||
set descriptions[70] "List all workspaces with their properties"
|
||||
set descriptions[71] "Focus the next window on a workspace"
|
||||
set descriptions[72] "Modify the window stack order of the active or specified window"
|
||||
set descriptions[73] "Toggle the current active window into a group"
|
||||
set descriptions[74] "Lock the groups"
|
||||
set descriptions[76] "Set all monitors' DPMS status"
|
||||
set descriptions[77] "Switch focus from current to previously focused window"
|
||||
set descriptions[78] "No Icon"
|
||||
set descriptions[79] "Execute a batch of commands separated by ;"
|
||||
set descriptions[80] "Send a notification using the built-in Hyprland notification system"
|
||||
set descriptions[82] "List all running Hyprland instances and their info"
|
||||
set descriptions[83] "Maximize no fullscreen"
|
||||
set descriptions[84] "Maximize and fullscreen"
|
||||
set descriptions[85] "Move the active window out of a group"
|
||||
set descriptions[86] "Close the active window"
|
||||
set descriptions[87] "HINT"
|
||||
set descriptions[88] "Move the focused window to a workspace"
|
||||
set descriptions[89] "Move the cursor to a specified position"
|
||||
set descriptions[90] "List all current config parsing errors"
|
||||
set descriptions[91] "Close a specified window"
|
||||
set descriptions[92] "Swap the active window with another window"
|
||||
set descriptions[93] "Apply a tag to the window"
|
||||
set descriptions[94] "Force the renderer to reload all resources and outputs"
|
||||
set descriptions[95] "Center the active window"
|
||||
set descriptions[97] "Focus the first window matching"
|
||||
set descriptions[98] "Set the hyprctl error string"
|
||||
set descriptions[101] "List all registered binds"
|
||||
set descriptions[102] "Print the Hyprland version: flags, commit and branch of build"
|
||||
set descriptions[103] "Prints the help message"
|
||||
set descriptions[104] "Toggle a special workspace on/off"
|
||||
set descriptions[105] "Toggle the focused window's fullscreen state"
|
||||
set descriptions[107] "None"
|
||||
set descriptions[108] "Issue a keyword to call a config keyword dynamically"
|
||||
set descriptions[109] "Toggle the current window to always be opaque"
|
||||
set descriptions[110] "ERROR"
|
||||
set descriptions[111] "Specify the Hyprland instance"
|
||||
set descriptions[112] "Toggle the current window's floating state"
|
||||
set descriptions[113] "Rename a workspace"
|
||||
set descriptions[115] "Get the active workspace name and its properties"
|
||||
set descriptions[117] "Get into a kill mode, where you can kill an app by clicking on it"
|
||||
set descriptions[119] "Allows adding/removing fake outputs to a specific backend"
|
||||
set descriptions[120] "Execute a Global Shortcut using the GlobalShortcuts portal"
|
||||
set descriptions[121] "Issue a dispatch to call a keybind dispatcher with an arg"
|
||||
set descriptions[122] "Force reload the config"
|
||||
set descriptions[124] "Output in JSON format"
|
||||
set descriptions[125] "Emits a custom event to socket2"
|
||||
set descriptions[126] "Prints the help message"
|
||||
set descriptions[128] "Current"
|
||||
set descriptions[129] "Get the active window name and its properties"
|
||||
set descriptions[131] "Dismiss all or up to amount of notifications"
|
||||
set descriptions[132] "Focus a monitor"
|
||||
set descriptions[133] "Move the focus in a direction"
|
||||
set descriptions[134] "Interact with a plugin"
|
||||
set descriptions[135] "Exit the compositor with no questions asked"
|
||||
set descriptions[136] "Change the workspace"
|
||||
set descriptions[137] "Sets the focused window’s fullscreen mode and the one sent to the client"
|
||||
set descriptions[138] "Get the config option status (values)"
|
||||
set descriptions[141] "List all decorations and their info"
|
||||
set descriptions[142] "Set the current window's floating state to false"
|
||||
set descriptions[144] "Return a parsable JSON with all the config options, descriptions, value types and ranges"
|
||||
set descriptions[145] "Resize a selected window"
|
||||
set descriptions[146] "Toggle the focused window's internal fullscreen state"
|
||||
set descriptions[147] "Print tail of the log"
|
||||
set descriptions[148] "Swap the active workspaces between two monitors"
|
||||
set descriptions[149] "Change the current mapping group"
|
||||
set descriptions[151] "Behave as moveintogroup"
|
||||
set descriptions[152] "Get the current cursor pos in global layout coordinates"
|
||||
set descriptions[154] "Focus the requested workspace"
|
||||
|
||||
set --local literal_transitions
|
||||
set literal_transitions[1] "set inputs 106 76 34 36 2 3 79 108 38 112 42 47 116 86 117 53 89 55 91 121 123 125 16 60 61 18 126 20 128 130 26 69 99 100 28 29 103 105; set tos 2 3 4 5 3 3 3 6 3 5 3 3 3 7 9 3 5 3 10 3 3 3 3 11 3 12 13 3 3 3 14 3 5 3 3 15 3 5"
|
||||
set literal_transitions[4] "set inputs 74 14 33 56 57 92 107 124 78 17 127 4 6 65 132 134 82 135 85 32 50 13 87 11 88 142; set tos 18 3 18 18 18 18 3 3 2 3 18 2 3 18 3 18 18 18 18 18 3 3 18 18 18 18"
|
||||
set literal_transitions[8] "set inputs 106 76 34 2 3 79 108 38 42 47 116 86 117 53 55 91 121 123 125 16 60 61 18 126 20 128 130 26 69 100 28 29 103; set tos 2 3 4 3 3 3 6 3 3 3 3 7 9 3 3 10 3 3 3 3 11 3 12 13 3 3 3 14 3 3 3 15 3"
|
||||
set literal_transitions[9] "set inputs 102 131 133 1 75 37 109 110 39 111 5 80 41 81 114 7 43 44 83 84 48 49 10 51 52 54 12 113 90 119 58 93 59 94 95 62 63 129 96 64 21 98 23 24 66 67 136 137 25 27 70 101 71 141 30 72; set tos 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3"
|
||||
set literal_transitions[10] "set inputs 118 115; set tos 21 17"
|
||||
set literal_transitions[12] "set inputs 104; set tos 3"
|
||||
set literal_transitions[14] "set inputs 22 120 31 140 122 45 73; set tos 2 2 2 2 2 2 2"
|
||||
set literal_transitions[15] "set inputs 40; set tos 3"
|
||||
set literal_transitions[16] "set inputs 139 97; set tos 3 3"
|
||||
set literal_transitions[18] "set inputs 19 8; set tos 3 3"
|
||||
set literal_transitions[19] "set inputs 77; set tos 20"
|
||||
set literal_transitions[20] "set inputs 35 46; set tos 5 5"
|
||||
set literal_transitions[21] "set inputs 9 68 15 138; set tos 3 3 3 3"
|
||||
set literal_transitions
|
||||
set literal_transitions[1] "set inputs 121 44 126 82 4 52 51 129 90 59 9 11 12 131 14 98 102 103 134 101 138 23 20 141 26 144 108 147 70 34 35 79 115 38 152 117 122 124 40 43 80 119; set tos 15 3 22 3 22 3 3 3 3 22 3 3 4 5 6 7 3 22 8 3 3 3 3 9 3 3 10 11 3 3 3 22 3 3 3 3 14 22 12 22 16 13"
|
||||
set literal_transitions[2] "set inputs 82 52 51 129 9 90 11 12 131 14 98 102 134 101 23 20 138 141 26 144 108 147 70 34 35 115 38 152 117 40 119 122 121 80 44; set tos 3 3 3 3 3 3 3 4 5 6 7 3 8 3 3 3 3 9 3 3 10 11 3 3 3 3 3 3 3 12 13 14 15 16 3"
|
||||
set literal_transitions[4] "set inputs 140 64 65 46 106 28 27 53 6 67 68 130 114 13 75 100 36 153 99 60 118 42 18 139 155 123; set tos 3 17 17 17 17 3 3 5 17 3 17 17 17 3 5 3 17 17 17 17 17 17 3 17 3 17"
|
||||
set literal_transitions[7] "set inputs 127; set tos 3"
|
||||
set literal_transitions[11] "set inputs 57; set tos 3"
|
||||
set literal_transitions[12] "set inputs 10; set tos 3"
|
||||
set literal_transitions[13] "set inputs 15 81; set tos 20 23"
|
||||
set literal_transitions[14] "set inputs 143; set tos 3"
|
||||
set literal_transitions[15] "set inputs 1 85 3 86 5 88 89 91 92 93 94 95 97 16 19 104 22 105 24 25 29 30 31 109 112 33 113 37 39 120 125 47 48 49 50 54 56 132 133 135 136 61 137 142 66 145 146 69 148 71 72 73 74 149 76 77 151 154; set tos 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 21 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3"
|
||||
set literal_transitions[16] "set inputs 87 7 110 62 78 55 63; set tos 5 5 5 5 5 5 5"
|
||||
set literal_transitions[17] "set inputs 41 45; set tos 3 3"
|
||||
set literal_transitions[18] "set inputs 8; set tos 24"
|
||||
set literal_transitions[19] "set inputs 32 150; set tos 3 3"
|
||||
set literal_transitions[20] "set inputs 96 17 116 21; set tos 3 3 3 3"
|
||||
set literal_transitions[21] "set inputs 107 83 128 2 84; set tos 3 3 3 3 3"
|
||||
set literal_transitions[24] "set inputs 58 111; set tos 22 22"
|
||||
|
||||
set --local match_anything_transitions_from 2 1 7 16 11 6 15 8 3 17 13 12
|
||||
set --local match_anything_transitions_to 3 8 3 3 3 16 19 8 19 3 3 19
|
||||
set match_anything_transitions_from 7 8 1 23 6 5 3 19 12 9 10 14 11 2
|
||||
set match_anything_transitions_to 18 3 2 3 19 3 18 3 18 3 3 18 18 2
|
||||
|
||||
set --local state 1
|
||||
set --local word_index 2
|
||||
set state 1
|
||||
set word_index 2
|
||||
while test $word_index -lt $COMP_CWORD
|
||||
set --local -- word $COMP_WORDS[$word_index]
|
||||
set -- word $COMP_WORDS[$word_index]
|
||||
|
||||
if set --query literal_transitions[$state] && test -n $literal_transitions[$state]
|
||||
set --local --erase inputs
|
||||
set --local --erase tos
|
||||
set --erase inputs
|
||||
set --erase tos
|
||||
eval $literal_transitions[$state]
|
||||
|
||||
if contains -- $word $literals
|
||||
set --local literal_matched 0
|
||||
set literal_matched 0
|
||||
for literal_id in (seq 1 (count $literals))
|
||||
if test $literals[$literal_id] = $word
|
||||
set --local index (contains --index -- $literal_id $inputs)
|
||||
set index (contains --index -- $literal_id $inputs)
|
||||
set state $tos[$index]
|
||||
set word_index (math $word_index + 1)
|
||||
set literal_matched 1
|
||||
@@ -181,7 +196,7 @@ function _hyprctl
|
||||
end
|
||||
|
||||
if set --query match_anything_transitions_from[$state] && test -n $match_anything_transitions_from[$state]
|
||||
set --local index (contains --index -- $state $match_anything_transitions_from)
|
||||
set index (contains --index -- $state $match_anything_transitions_from)
|
||||
set state $match_anything_transitions_to[$index]
|
||||
set word_index (math $word_index + 1)
|
||||
continue
|
||||
@@ -191,8 +206,8 @@ function _hyprctl
|
||||
end
|
||||
|
||||
if set --query literal_transitions[$state] && test -n $literal_transitions[$state]
|
||||
set --local --erase inputs
|
||||
set --local --erase tos
|
||||
set --erase inputs
|
||||
set --erase tos
|
||||
eval $literal_transitions[$state]
|
||||
for literal_id in $inputs
|
||||
if test -n $descriptions[$literal_id]
|
||||
@@ -203,14 +218,14 @@ function _hyprctl
|
||||
end
|
||||
end
|
||||
|
||||
set command_states 6 17 13 11
|
||||
set command_ids 2 3 4 1
|
||||
set command_states 8 23 9 6
|
||||
set command_ids 1 2 4 3
|
||||
if contains $state $command_states
|
||||
set --local index (contains --index $state $command_states)
|
||||
set --local function_id $command_ids[$index]
|
||||
set --local function_name _hyprctl_$function_id
|
||||
set --local --erase inputs
|
||||
set --local --erase tos
|
||||
set index (contains --index $state $command_states)
|
||||
set function_id $command_ids[$index]
|
||||
set function_name _hyprctl_$function_id
|
||||
set --erase inputs
|
||||
set --erase tos
|
||||
$function_name "$COMP_WORDS[$COMP_CWORD]"
|
||||
end
|
||||
|
||||
|
@@ -9,13 +9,14 @@ hyprctl [<OPTIONS>]... <ARGUMENTS>
|
||||
| (-r) "Refresh state after issuing the command"
|
||||
| (--batch) "Execute a batch of commands separated by ;"
|
||||
| (-q | --quiet) "Disable output"
|
||||
| (-h | --help) "Prints the help message"
|
||||
;
|
||||
|
||||
<WINDOWS> ::= {{{ hyprctl clients | grep class | awk '{print $2}' }}};
|
||||
<WINDOWS> ::= {{{ hyprctl clients | awk '/class/{print $2}' }}};
|
||||
|
||||
<AVAILABLE_PLUGINS> ::= {{{ hyprpm list | grep "Plugin" | awk '{print $4}' }}};
|
||||
<AVAILABLE_PLUGINS> ::= {{{ hyprpm list | awk '/Plugin/{print $4}' }}};
|
||||
|
||||
<MONITORS> ::= {{{ hyprctl monitors | grep Monitor | awk '{ print $2 }' }}};
|
||||
<MONITORS> ::= {{{ hyprctl monitors | awk '/Monitor/{ print $2 }' }}};
|
||||
|
||||
<KEYBOARDS> ::= {{{ hyprctl devices | sed -n '/Keyboard at/{n; s/^\s\+//; p}' }}};
|
||||
|
||||
@@ -59,16 +60,18 @@ hyprctl [<OPTIONS>]... <ARGUMENTS>
|
||||
|
||||
<ARGUMENTS> ::= (activewindow) "Get the active window name and its properties"
|
||||
| (activeworkspace) "Get the active workspace name and its properties"
|
||||
| (animations) "Gets the current config info about animations and beziers"
|
||||
| (binds) "List all registered binds"
|
||||
| (clients) "List all windows with their properties"
|
||||
| (configerrors) "List all current config parsing errors"
|
||||
| (cursorpos) "Get the current cursor pos in global layout coordinates"
|
||||
| (decorations <WINDOWS>) "List all decorations and their info"
|
||||
| (descriptions) "Return a parsable JSON with all the config options, descriptions, value types and ranges"
|
||||
| (devices) "List all connected keyboards and mice"
|
||||
| (dismissnotify <NUM>) "Dismiss all or up to amount of notifications"
|
||||
| (dispatch <DISPATCHERS>) "Issue a dispatch to call a keybind dispatcher with an arg"
|
||||
| (getoption) "Get the config option status (values)"
|
||||
| (globalshortcuts) ""
|
||||
| (globalshortcuts) "Lists all global shortcuts"
|
||||
| (hyprpaper) "Interact with hyprpaper if present"
|
||||
| (instances) "List all running Hyprland instances and their info"
|
||||
| (keyword <KEYWORDS>) "Issue a keyword to call a config keyword dynamically"
|
||||
@@ -79,8 +82,8 @@ hyprctl [<OPTIONS>]... <ARGUMENTS>
|
||||
| (notify <NOTIFICATION_TYPES> <NUM>) "Send a notification using the built-in Hyprland notification system"
|
||||
| (output (create (wayland | x11 | headless | auto) | remove <MONITORS>)) "Allows adding/removing fake outputs to a specific backend"
|
||||
| (plugin <AVAILABLE_PLUGINS>) "Interact with a plugin"
|
||||
| (reload) "Force reload the config"
|
||||
| (rollinglog) "Print tail of the log"
|
||||
| (reload [config-only]) "Force reload the config"
|
||||
| (rollinglog [-f]) "Print tail of the log"
|
||||
| (setcursor) "Set the cursor theme and reloads the cursor manager"
|
||||
| (seterror [disable]) "Set the hyprctl error string"
|
||||
| (setprop <PROPS>) "Set a property of a window"
|
||||
@@ -92,6 +95,13 @@ hyprctl [<OPTIONS>]... <ARGUMENTS>
|
||||
| (workspaces) "List all workspaces with their properties"
|
||||
;
|
||||
|
||||
<WINDOW_STATE> ::= (-1) "Current"
|
||||
| (0) "None"
|
||||
| (1) "Maximize no fullscreen"
|
||||
| (2) "Fullscreen"
|
||||
| (3) "Maximize and fullscreen"
|
||||
;
|
||||
|
||||
<DISPATCHERS> ::= (exec) "Execute a shell command"
|
||||
| (execr) "Execute a raw shell command"
|
||||
| (pass) "Pass the key to a specified window"
|
||||
@@ -106,6 +116,7 @@ hyprctl [<OPTIONS>]... <ARGUMENTS>
|
||||
| (settiled) "Set the current window's floating state to false"
|
||||
| (fullscreen) "Toggle the focused window's fullscreen state"
|
||||
| (fakefullscreen) "Toggle the focused window's internal fullscreen state"
|
||||
| (fullscreenstate <WINDOW_STATE>) "Sets the focused window’s fullscreen mode and the one sent to the client"
|
||||
| (dpms) "Set all monitors' DPMS status"
|
||||
| (pin) "Pin a window"
|
||||
| (movefocus) "Move the focus in a direction"
|
||||
@@ -148,4 +159,5 @@ hyprctl [<OPTIONS>]... <ARGUMENTS>
|
||||
| (setignoregrouplock) "Temporarily enable or disable binds:ignore_group_lock"
|
||||
| (global) "Execute a Global Shortcut using the GlobalShortcuts portal"
|
||||
| (submap) "Change the current mapping group"
|
||||
| (event) "Emits a custom event to socket2"
|
||||
;
|
||||
|
@@ -1,143 +1,160 @@
|
||||
_hyprctl_cmd_2 () {
|
||||
hyprctl monitors | grep Monitor | awk '{ print $2 }'
|
||||
#compdef hyprctl
|
||||
|
||||
_hyprctl_cmd_1 () {
|
||||
hyprctl monitors | awk '/Monitor/{ print $2 }'
|
||||
}
|
||||
|
||||
_hyprctl_cmd_3 () {
|
||||
hyprpm list | grep "Plugin" | awk '{print $4}'
|
||||
hyprctl clients | awk '/class/{print $2}'
|
||||
}
|
||||
|
||||
_hyprctl_cmd_0 () {
|
||||
hyprctl clients | grep class | awk '{print $2}'
|
||||
}
|
||||
|
||||
_hyprctl_cmd_1 () {
|
||||
_hyprctl_cmd_2 () {
|
||||
hyprctl devices | sed -n '/Keyboard at/{n; s/^\s\+//; p}'
|
||||
}
|
||||
|
||||
_hyprctl_cmd_0 () {
|
||||
hyprpm list | awk '/Plugin/{print $4}'
|
||||
}
|
||||
|
||||
_hyprctl () {
|
||||
local -a literals=("cyclenext" "globalshortcuts" "cursorpos" "bordersize" "renameworkspace" "animationstyle" "focuswindow" "0" "auto" "swapnext" "forceallowsinput" "moveactive" "activebordercolor" "alphafullscreen" "wayland" "layers" "minsize" "monitors" "1" "kill" "settiled" "3" "focusmonitor" "swapwindow" "moveoutofgroup" "notify" "movecursor" "setcursor" "seterror" "movecurrentworkspacetomonitor" "4" "nomaxsize" "forcenoanims" "setprop" "-i" "-q" "togglefloating" "workspacerules" "movetoworkspace" "disable" "setignoregrouplock" "workspaces" "movegroupwindow" "closewindow" "0" "--instance" "binds" "movewindow" "splitratio" "alpha" "denywindowfromgroup" "workspace" "configerrors" "togglegroup" "getoption" "forceopaque" "keepaspectratio" "killactive" "pass" "decorations" "devices" "focuscurrentorlast" "submap" "global" "alphafullscreenoverride" "forcerendererreload" "movewindowpixel" "headless" "version" "dpms" "resizeactive" "moveintogroup" "5" "alphaoverride" "setfloating" "rollinglog" "::=" "rounding" "layouts" "moveworkspacetomonitor" "exec" "alphainactiveoverride" "alterzorder" "fakefullscreen" "nofocus" "keyword" "forcenoborder" "forcenodim" "--quiet" "pin" "output" "forcenoblur" "togglespecialworkspace" "fullscreen" "toggleopaque" "focusworkspaceoncurrentmonitor" "next" "changegroupactive" "-j" "instances" "execr" "exit" "clients" "all" "--batch" "dismissnotify" "inactivebordercolor" "switchxkblayout" "movetoworkspacesilent" "tagwindow" "movewindoworgroup" "-r" "movefocus" "focusurgentorlast" "remove" "activeworkspace" "dispatch" "create" "centerwindow" "2" "hyprpaper" "-1" "reload" "alphainactive" "systeminfo" "plugin" "dimaround" "activewindow" "swapactiveworkspaces" "splash" "sendshortcut" "maxsize" "lockactivegroup" "windowdancecompat" "forceopaqueoverriden" "lockgroups" "movecursortocorner" "x11" "prev" "1" "resizewindowpixel" "forcenoshadow")
|
||||
local -a literals=("resizeactive" "2" "changegroupactive" "-r" "moveintogroup" "forceallowsinput" "4" "::=" "systeminfo" "all" "layouts" "setprop" "animationstyle" "switchxkblayout" "create" "denywindowfromgroup" "headless" "activebordercolor" "exec" "setcursor" "wayland" "focusurgentorlast" "workspacerules" "movecurrentworkspacetomonitor" "movetoworkspacesilent" "hyprpaper" "alpha" "inactivebordercolor" "movegroupwindow" "movecursortocorner" "movewindowpixel" "prev" "movewindow" "globalshortcuts" "clients" "dimaround" "setignoregrouplock" "splash" "execr" "monitors" "0" "forcenoborder" "-q" "animations" "1" "nomaxsize" "splitratio" "moveactive" "pass" "swapnext" "devices" "layers" "rounding" "lockactivegroup" "5" "moveworkspacetomonitor" "-f" "-i" "--quiet" "forcenodim" "pin" "0" "1" "forceopaque" "forcenoshadow" "setfloating" "minsize" "alphaoverride" "sendshortcut" "workspaces" "cyclenext" "alterzorder" "togglegroup" "lockgroups" "bordersize" "dpms" "focuscurrentorlast" "-1" "--batch" "notify" "remove" "instances" "1" "3" "moveoutofgroup" "killactive" "2" "movetoworkspace" "movecursor" "configerrors" "closewindow" "swapwindow" "tagwindow" "forcerendererreload" "centerwindow" "auto" "focuswindow" "seterror" "nofocus" "alphafullscreen" "binds" "version" "-h" "togglespecialworkspace" "fullscreen" "windowdancecompat" "0" "keyword" "toggleopaque" "3" "--instance" "togglefloating" "renameworkspace" "alphafullscreenoverride" "activeworkspace" "x11" "kill" "forceopaqueoverriden" "output" "global" "dispatch" "reload" "forcenoblur" "-j" "event" "--help" "disable" "-1" "activewindow" "keepaspectratio" "dismissnotify" "focusmonitor" "movefocus" "plugin" "exit" "workspace" "fullscreenstate" "getoption" "alphainactiveoverride" "alphainactive" "decorations" "settiled" "config-only" "descriptions" "resizewindowpixel" "fakefullscreen" "rollinglog" "swapactiveworkspaces" "submap" "next" "movewindoworgroup" "cursorpos" "forcenoanims" "focusworkspaceoncurrentmonitor" "maxsize")
|
||||
|
||||
local -A descriptions
|
||||
descriptions[1]="Focus the next window on a workspace"
|
||||
descriptions[3]="Get the current cursor pos in global layout coordinates"
|
||||
descriptions[5]="Rename a workspace"
|
||||
descriptions[7]="Focus the first window matching"
|
||||
descriptions[10]="Swap the focused window with the next window"
|
||||
descriptions[12]="Move the active window"
|
||||
descriptions[16]="List the layers"
|
||||
descriptions[18]="List active outputs with their properties"
|
||||
descriptions[20]="Get into a kill mode, where you can kill an app by clicking on it"
|
||||
descriptions[21]="Set the current window's floating state to false"
|
||||
descriptions[22]="ERROR"
|
||||
descriptions[23]="Focus a monitor"
|
||||
descriptions[24]="Swap the active window with another window"
|
||||
descriptions[25]="Move the active window out of a group"
|
||||
descriptions[26]="Send a notification using the built-in Hyprland notification system"
|
||||
descriptions[27]="Move the cursor to a specified position"
|
||||
descriptions[28]="Set the cursor theme and reloads the cursor manager"
|
||||
descriptions[29]="Set the hyprctl error string"
|
||||
descriptions[30]="Move the active workspace to a monitor"
|
||||
descriptions[31]="CONFUSED"
|
||||
descriptions[34]="Set a property of a window"
|
||||
descriptions[35]="Specify the Hyprland instance"
|
||||
descriptions[36]="Disable output"
|
||||
descriptions[37]="Toggle the current window's floating state"
|
||||
descriptions[38]="Get the list of defined workspace rules"
|
||||
descriptions[39]="Move the focused window to a workspace"
|
||||
descriptions[41]="Temporarily enable or disable binds:ignore_group_lock"
|
||||
descriptions[42]="List all workspaces with their properties"
|
||||
descriptions[43]="Swap the active window with the next or previous in a group"
|
||||
descriptions[44]="Close a specified window"
|
||||
descriptions[45]="WARNING"
|
||||
descriptions[46]="Specify the Hyprland instance"
|
||||
descriptions[47]="List all registered binds"
|
||||
descriptions[48]="Move the active window in a direction or to a monitor"
|
||||
descriptions[49]="Change the split ratio"
|
||||
descriptions[51]="Prohibit the active window from becoming or being inserted into group"
|
||||
descriptions[52]="Change the workspace"
|
||||
descriptions[53]="List all current config parsing errors"
|
||||
descriptions[54]="Toggle the current active window into a group"
|
||||
descriptions[55]="Get the config option status (values)"
|
||||
descriptions[58]="Close the active window"
|
||||
descriptions[59]="Pass the key to a specified window"
|
||||
descriptions[60]="List all decorations and their info"
|
||||
descriptions[61]="List all connected keyboards and mice"
|
||||
descriptions[62]="Switch focus from current to previously focused window"
|
||||
descriptions[63]="Change the current mapping group"
|
||||
descriptions[64]="Execute a Global Shortcut using the GlobalShortcuts portal"
|
||||
descriptions[66]="Force the renderer to reload all resources and outputs"
|
||||
descriptions[67]="Move a selected window"
|
||||
descriptions[69]="Print the Hyprland version: flags, commit and branch of build"
|
||||
descriptions[70]="Set all monitors' DPMS status"
|
||||
descriptions[71]="Resize the active window"
|
||||
descriptions[72]="Move the active window into a group"
|
||||
descriptions[73]="OK"
|
||||
descriptions[75]="Set the current window's floating state to true"
|
||||
descriptions[76]="Print tail of the log"
|
||||
descriptions[79]="List all layouts available (including plugin ones)"
|
||||
descriptions[80]="Move a workspace to a monitor"
|
||||
descriptions[81]="Execute a shell command"
|
||||
descriptions[83]="Modify the window stack order of the active or specified window"
|
||||
descriptions[84]="Toggle the focused window's internal fullscreen state"
|
||||
descriptions[86]="Issue a keyword to call a config keyword dynamically"
|
||||
descriptions[89]="Disable output"
|
||||
descriptions[90]="Pin a window"
|
||||
descriptions[91]="Allows adding/removing fake outputs to a specific backend"
|
||||
descriptions[93]="Toggle a special workspace on/off"
|
||||
descriptions[94]="Toggle the focused window's fullscreen state"
|
||||
descriptions[95]="Toggle the current window to always be opaque"
|
||||
descriptions[96]="Focus the requested workspace"
|
||||
descriptions[98]="Switch to the next window in a group"
|
||||
descriptions[99]="Output in JSON format"
|
||||
descriptions[100]="List all running Hyprland instances and their info"
|
||||
descriptions[101]="Execute a raw shell command"
|
||||
descriptions[102]="Exit the compositor with no questions asked"
|
||||
descriptions[103]="List all windows with their properties"
|
||||
descriptions[105]="Execute a batch of commands separated by ;"
|
||||
descriptions[106]="Dismiss all or up to amount of notifications"
|
||||
descriptions[108]="Set the xkb layout index for a keyboard"
|
||||
descriptions[109]="Move window doesnt switch to the workspace"
|
||||
descriptions[110]="Apply a tag to the window"
|
||||
descriptions[111]="Behave as moveintogroup"
|
||||
descriptions[112]="Refresh state after issuing the command"
|
||||
descriptions[113]="Move the focus in a direction"
|
||||
descriptions[114]="Focus the urgent window or the last window"
|
||||
descriptions[116]="Get the active workspace name and its properties"
|
||||
descriptions[117]="Issue a dispatch to call a keybind dispatcher with an arg"
|
||||
descriptions[119]="Center the active window"
|
||||
descriptions[120]="HINT"
|
||||
descriptions[121]="Interact with hyprpaper if present"
|
||||
descriptions[122]="No Icon"
|
||||
descriptions[123]="Force reload the config"
|
||||
descriptions[125]="Print system info"
|
||||
descriptions[126]="Interact with a plugin"
|
||||
descriptions[128]="Get the active window name and its properties"
|
||||
descriptions[129]="Swap the active workspaces between two monitors"
|
||||
descriptions[130]="Print the current random splash"
|
||||
descriptions[131]="On shortcut X sends shortcut Y to a specified window"
|
||||
descriptions[133]="Lock the focused group"
|
||||
descriptions[136]="Lock the groups"
|
||||
descriptions[137]="Move the cursor to the corner of the active window"
|
||||
descriptions[140]="INFO"
|
||||
descriptions[141]="Resize a selected window"
|
||||
descriptions[1]="Resize the active window"
|
||||
descriptions[2]="Fullscreen"
|
||||
descriptions[3]="Switch to the next window in a group"
|
||||
descriptions[4]="Refresh state after issuing the command"
|
||||
descriptions[5]="Move the active window into a group"
|
||||
descriptions[7]="CONFUSED"
|
||||
descriptions[9]="Print system info"
|
||||
descriptions[11]="List all layouts available (including plugin ones)"
|
||||
descriptions[12]="Set a property of a window"
|
||||
descriptions[14]="Set the xkb layout index for a keyboard"
|
||||
descriptions[16]="Prohibit the active window from becoming or being inserted into group"
|
||||
descriptions[19]="Execute a shell command"
|
||||
descriptions[20]="Set the cursor theme and reloads the cursor manager"
|
||||
descriptions[22]="Focus the urgent window or the last window"
|
||||
descriptions[23]="Get the list of defined workspace rules"
|
||||
descriptions[24]="Move the active workspace to a monitor"
|
||||
descriptions[25]="Move window doesnt switch to the workspace"
|
||||
descriptions[26]="Interact with hyprpaper if present"
|
||||
descriptions[29]="Swap the active window with the next or previous in a group"
|
||||
descriptions[30]="Move the cursor to the corner of the active window"
|
||||
descriptions[31]="Move a selected window"
|
||||
descriptions[33]="Move the active window in a direction or to a monitor"
|
||||
descriptions[34]="Lists all global shortcuts"
|
||||
descriptions[35]="List all windows with their properties"
|
||||
descriptions[37]="Temporarily enable or disable binds:ignore_group_lock"
|
||||
descriptions[38]="Print the current random splash"
|
||||
descriptions[39]="Execute a raw shell command"
|
||||
descriptions[40]="List active outputs with their properties"
|
||||
descriptions[43]="Disable output"
|
||||
descriptions[44]="Gets the current config info about animations and beziers"
|
||||
descriptions[47]="Change the split ratio"
|
||||
descriptions[48]="Move the active window"
|
||||
descriptions[49]="Pass the key to a specified window"
|
||||
descriptions[50]="Swap the focused window with the next window"
|
||||
descriptions[51]="List all connected keyboards and mice"
|
||||
descriptions[52]="List the layers"
|
||||
descriptions[54]="Lock the focused group"
|
||||
descriptions[55]="OK"
|
||||
descriptions[56]="Move a workspace to a monitor"
|
||||
descriptions[58]="Specify the Hyprland instance"
|
||||
descriptions[59]="Disable output"
|
||||
descriptions[61]="Pin a window"
|
||||
descriptions[62]="WARNING"
|
||||
descriptions[63]="INFO"
|
||||
descriptions[66]="Set the current window's floating state to true"
|
||||
descriptions[69]="On shortcut X sends shortcut Y to a specified window"
|
||||
descriptions[70]="List all workspaces with their properties"
|
||||
descriptions[71]="Focus the next window on a workspace"
|
||||
descriptions[72]="Modify the window stack order of the active or specified window"
|
||||
descriptions[73]="Toggle the current active window into a group"
|
||||
descriptions[74]="Lock the groups"
|
||||
descriptions[76]="Set all monitors' DPMS status"
|
||||
descriptions[77]="Switch focus from current to previously focused window"
|
||||
descriptions[78]="No Icon"
|
||||
descriptions[79]="Execute a batch of commands separated by ;"
|
||||
descriptions[80]="Send a notification using the built-in Hyprland notification system"
|
||||
descriptions[82]="List all running Hyprland instances and their info"
|
||||
descriptions[83]="Maximize no fullscreen"
|
||||
descriptions[84]="Maximize and fullscreen"
|
||||
descriptions[85]="Move the active window out of a group"
|
||||
descriptions[86]="Close the active window"
|
||||
descriptions[87]="HINT"
|
||||
descriptions[88]="Move the focused window to a workspace"
|
||||
descriptions[89]="Move the cursor to a specified position"
|
||||
descriptions[90]="List all current config parsing errors"
|
||||
descriptions[91]="Close a specified window"
|
||||
descriptions[92]="Swap the active window with another window"
|
||||
descriptions[93]="Apply a tag to the window"
|
||||
descriptions[94]="Force the renderer to reload all resources and outputs"
|
||||
descriptions[95]="Center the active window"
|
||||
descriptions[97]="Focus the first window matching"
|
||||
descriptions[98]="Set the hyprctl error string"
|
||||
descriptions[101]="List all registered binds"
|
||||
descriptions[102]="Print the Hyprland version: flags, commit and branch of build"
|
||||
descriptions[103]="Prints the help message"
|
||||
descriptions[104]="Toggle a special workspace on/off"
|
||||
descriptions[105]="Toggle the focused window's fullscreen state"
|
||||
descriptions[107]="None"
|
||||
descriptions[108]="Issue a keyword to call a config keyword dynamically"
|
||||
descriptions[109]="Toggle the current window to always be opaque"
|
||||
descriptions[110]="ERROR"
|
||||
descriptions[111]="Specify the Hyprland instance"
|
||||
descriptions[112]="Toggle the current window's floating state"
|
||||
descriptions[113]="Rename a workspace"
|
||||
descriptions[115]="Get the active workspace name and its properties"
|
||||
descriptions[117]="Get into a kill mode, where you can kill an app by clicking on it"
|
||||
descriptions[119]="Allows adding/removing fake outputs to a specific backend"
|
||||
descriptions[120]="Execute a Global Shortcut using the GlobalShortcuts portal"
|
||||
descriptions[121]="Issue a dispatch to call a keybind dispatcher with an arg"
|
||||
descriptions[122]="Force reload the config"
|
||||
descriptions[124]="Output in JSON format"
|
||||
descriptions[125]="Emits a custom event to socket2"
|
||||
descriptions[126]="Prints the help message"
|
||||
descriptions[128]="Current"
|
||||
descriptions[129]="Get the active window name and its properties"
|
||||
descriptions[131]="Dismiss all or up to amount of notifications"
|
||||
descriptions[132]="Focus a monitor"
|
||||
descriptions[133]="Move the focus in a direction"
|
||||
descriptions[134]="Interact with a plugin"
|
||||
descriptions[135]="Exit the compositor with no questions asked"
|
||||
descriptions[136]="Change the workspace"
|
||||
descriptions[137]="Sets the focused window’s fullscreen mode and the one sent to the client"
|
||||
descriptions[138]="Get the config option status (values)"
|
||||
descriptions[141]="List all decorations and their info"
|
||||
descriptions[142]="Set the current window's floating state to false"
|
||||
descriptions[144]="Return a parsable JSON with all the config options, descriptions, value types and ranges"
|
||||
descriptions[145]="Resize a selected window"
|
||||
descriptions[146]="Toggle the focused window's internal fullscreen state"
|
||||
descriptions[147]="Print tail of the log"
|
||||
descriptions[148]="Swap the active workspaces between two monitors"
|
||||
descriptions[149]="Change the current mapping group"
|
||||
descriptions[151]="Behave as moveintogroup"
|
||||
descriptions[152]="Get the current cursor pos in global layout coordinates"
|
||||
descriptions[154]="Focus the requested workspace"
|
||||
|
||||
local -A literal_transitions
|
||||
literal_transitions[1]="([106]=2 [76]=3 [34]=4 [36]=5 [2]=3 [3]=3 [79]=3 [108]=6 [38]=3 [112]=5 [42]=3 [47]=3 [116]=3 [86]=7 [117]=9 [53]=3 [89]=5 [55]=3 [91]=10 [121]=3 [123]=3 [125]=3 [16]=3 [60]=11 [61]=3 [18]=12 [126]=13 [20]=3 [128]=3 [130]=3 [26]=14 [69]=3 [99]=5 [100]=3 [28]=3 [29]=15 [103]=3 [105]=5)"
|
||||
literal_transitions[4]="([74]=18 [14]=3 [33]=18 [56]=18 [57]=18 [92]=18 [107]=3 [124]=3 [78]=2 [17]=3 [127]=18 [4]=2 [6]=3 [65]=18 [132]=3 [134]=18 [82]=18 [135]=18 [85]=18 [32]=18 [50]=3 [13]=3 [87]=18 [11]=18 [88]=18 [142]=18)"
|
||||
literal_transitions[8]="([106]=2 [76]=3 [34]=4 [2]=3 [3]=3 [79]=3 [108]=6 [38]=3 [42]=3 [47]=3 [116]=3 [86]=7 [117]=9 [53]=3 [55]=3 [91]=10 [121]=3 [123]=3 [125]=3 [16]=3 [60]=11 [61]=3 [18]=12 [126]=13 [20]=3 [128]=3 [130]=3 [26]=14 [69]=3 [100]=3 [28]=3 [29]=15 [103]=3)"
|
||||
literal_transitions[9]="([102]=3 [131]=3 [133]=3 [1]=3 [75]=3 [37]=3 [109]=3 [110]=3 [39]=3 [111]=3 [5]=3 [80]=3 [41]=3 [81]=3 [114]=3 [7]=3 [43]=3 [44]=3 [83]=3 [84]=3 [48]=3 [49]=3 [10]=3 [51]=3 [52]=3 [54]=3 [12]=3 [113]=3 [90]=3 [119]=3 [58]=3 [93]=3 [59]=3 [94]=3 [95]=3 [62]=3 [63]=3 [129]=3 [96]=3 [64]=3 [21]=3 [98]=3 [23]=3 [24]=3 [66]=3 [67]=3 [136]=3 [137]=3 [25]=3 [27]=3 [70]=3 [101]=3 [71]=3 [141]=3 [30]=3 [72]=3)"
|
||||
literal_transitions[10]="([118]=21 [115]=17)"
|
||||
literal_transitions[12]="([104]=3)"
|
||||
literal_transitions[14]="([22]=2 [120]=2 [31]=2 [140]=2 [122]=2 [45]=2 [73]=2)"
|
||||
literal_transitions[15]="([40]=3)"
|
||||
literal_transitions[16]="([139]=3 [97]=3)"
|
||||
literal_transitions[18]="([19]=3 [8]=3)"
|
||||
literal_transitions[19]="([77]=20)"
|
||||
literal_transitions[20]="([35]=5 [46]=5)"
|
||||
literal_transitions[21]="([9]=3 [68]=3 [15]=3 [138]=3)"
|
||||
literal_transitions[1]="([121]=15 [44]=3 [126]=22 [82]=3 [4]=22 [52]=3 [51]=3 [129]=3 [90]=3 [59]=22 [9]=3 [11]=3 [12]=4 [131]=5 [14]=6 [98]=7 [102]=3 [103]=22 [134]=8 [101]=3 [138]=3 [23]=3 [20]=3 [141]=9 [26]=3 [144]=3 [108]=10 [147]=11 [70]=3 [34]=3 [35]=3 [79]=22 [115]=3 [38]=3 [152]=3 [117]=3 [122]=14 [124]=22 [40]=12 [43]=22 [80]=16 [119]=13)"
|
||||
literal_transitions[2]="([82]=3 [52]=3 [51]=3 [129]=3 [9]=3 [90]=3 [11]=3 [12]=4 [131]=5 [14]=6 [98]=7 [102]=3 [134]=8 [101]=3 [23]=3 [20]=3 [138]=3 [141]=9 [26]=3 [144]=3 [108]=10 [147]=11 [70]=3 [34]=3 [35]=3 [115]=3 [38]=3 [152]=3 [117]=3 [40]=12 [119]=13 [122]=14 [121]=15 [80]=16 [44]=3)"
|
||||
literal_transitions[4]="([140]=3 [64]=17 [65]=17 [46]=17 [106]=17 [28]=3 [27]=3 [53]=5 [6]=17 [67]=3 [68]=17 [130]=17 [114]=17 [13]=3 [75]=5 [100]=3 [36]=17 [153]=17 [99]=17 [60]=17 [118]=17 [42]=17 [18]=3 [139]=17 [155]=3 [123]=17)"
|
||||
literal_transitions[7]="([127]=3)"
|
||||
literal_transitions[11]="([57]=3)"
|
||||
literal_transitions[12]="([10]=3)"
|
||||
literal_transitions[13]="([15]=20 [81]=23)"
|
||||
literal_transitions[14]="([143]=3)"
|
||||
literal_transitions[15]="([1]=3 [85]=3 [3]=3 [86]=3 [5]=3 [88]=3 [89]=3 [91]=3 [92]=3 [93]=3 [94]=3 [95]=3 [97]=3 [16]=3 [19]=3 [104]=3 [22]=3 [105]=3 [24]=3 [25]=3 [29]=3 [30]=3 [31]=3 [109]=3 [112]=3 [33]=3 [113]=3 [37]=3 [39]=3 [120]=3 [125]=3 [47]=3 [48]=3 [49]=3 [50]=3 [54]=3 [56]=3 [132]=3 [133]=3 [135]=3 [136]=3 [61]=3 [137]=21 [142]=3 [66]=3 [145]=3 [146]=3 [69]=3 [148]=3 [71]=3 [72]=3 [73]=3 [74]=3 [149]=3 [76]=3 [77]=3 [151]=3 [154]=3)"
|
||||
literal_transitions[16]="([87]=5 [7]=5 [110]=5 [62]=5 [78]=5 [55]=5 [63]=5)"
|
||||
literal_transitions[17]="([41]=3 [45]=3)"
|
||||
literal_transitions[18]="([8]=24)"
|
||||
literal_transitions[19]="([32]=3 [150]=3)"
|
||||
literal_transitions[20]="([96]=3 [17]=3 [116]=3 [21]=3)"
|
||||
literal_transitions[21]="([107]=3 [83]=3 [128]=3 [2]=3 [84]=3)"
|
||||
literal_transitions[24]="([58]=22 [111]=22)"
|
||||
|
||||
local -A match_anything_transitions
|
||||
match_anything_transitions=([2]=3 [1]=8 [7]=3 [16]=3 [11]=3 [6]=16 [15]=19 [8]=8 [3]=19 [17]=3 [13]=3 [12]=19)
|
||||
match_anything_transitions=([7]=18 [8]=3 [1]=2 [23]=3 [6]=19 [5]=3 [3]=18 [19]=3 [12]=18 [9]=3 [10]=3 [14]=18 [11]=18 [2]=2)
|
||||
|
||||
declare -A subword_transitions
|
||||
|
||||
@@ -197,7 +214,7 @@ _hyprctl () {
|
||||
fi
|
||||
done
|
||||
fi
|
||||
local -A commands=([6]=1 [17]=2 [13]=3 [11]=0)
|
||||
local -A commands=([8]=0 [23]=1 [9]=3 [6]=2)
|
||||
|
||||
if [[ -v "commands[$state]" ]]; then
|
||||
local command_id=${commands[$state]}
|
||||
@@ -250,4 +267,8 @@ _hyprctl () {
|
||||
return 0
|
||||
}
|
||||
|
||||
compdef _hyprctl hyprctl
|
||||
if [[ $ZSH_EVAL_CONTEXT =~ :file$ ]]; then
|
||||
compdef _hyprctl hyprctl
|
||||
else
|
||||
_hyprctl
|
||||
fi
|
||||
|
@@ -1,9 +1,9 @@
|
||||
#include <ctype.h>
|
||||
#include <cctype>
|
||||
#include <netdb.h>
|
||||
#include <netinet/in.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
@@ -12,7 +12,7 @@
|
||||
#include <unistd.h>
|
||||
#include <ranges>
|
||||
#include <algorithm>
|
||||
#include <signal.h>
|
||||
#include <csignal>
|
||||
#include <format>
|
||||
|
||||
#include <iostream>
|
||||
@@ -22,8 +22,12 @@
|
||||
#include <vector>
|
||||
#include <deque>
|
||||
#include <filesystem>
|
||||
#include <stdarg.h>
|
||||
#include <cstdarg>
|
||||
#include <regex>
|
||||
#include <sys/socket.h>
|
||||
#include <hyprutils/string/String.hpp>
|
||||
#include <cstring>
|
||||
using namespace Hyprutils::String;
|
||||
|
||||
#include "Strings.hpp"
|
||||
|
||||
@@ -44,7 +48,7 @@ void log(std::string str) {
|
||||
if (quiet)
|
||||
return;
|
||||
|
||||
std::cout << str;
|
||||
std::cout << str << "\n";
|
||||
}
|
||||
|
||||
std::string getRuntimeDir() {
|
||||
@@ -98,13 +102,53 @@ std::vector<SInstanceData> instances() {
|
||||
return result;
|
||||
}
|
||||
|
||||
int request(std::string arg, int minArgs = 0) {
|
||||
static volatile bool sigintReceived = false;
|
||||
void intHandler(int sig) {
|
||||
sigintReceived = true;
|
||||
std::cout << "[hyprctl] SIGINT received, closing connection" << std::endl;
|
||||
}
|
||||
|
||||
int rollingRead(const int socket) {
|
||||
sigintReceived = false;
|
||||
signal(SIGINT, intHandler);
|
||||
|
||||
constexpr size_t BUFFER_SIZE = 8192;
|
||||
std::array<char, BUFFER_SIZE> buffer = {0};
|
||||
long sizeWritten = 0;
|
||||
std::cout << "[hyprctl] reading from socket following up log:" << std::endl;
|
||||
while (!sigintReceived) {
|
||||
sizeWritten = read(socket, buffer.data(), BUFFER_SIZE);
|
||||
if (sizeWritten < 0 && errno != EAGAIN) {
|
||||
if (errno != EINTR)
|
||||
std::cout << "Couldn't read (5) " << strerror(errno) << ":" << errno << std::endl;
|
||||
close(socket);
|
||||
return 5;
|
||||
}
|
||||
|
||||
if (sizeWritten == 0)
|
||||
break;
|
||||
|
||||
if (sizeWritten > 0) {
|
||||
std::cout << std::string(buffer.data(), sizeWritten);
|
||||
buffer.fill('\0');
|
||||
}
|
||||
|
||||
usleep(100000);
|
||||
}
|
||||
close(socket);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int request(std::string arg, int minArgs = 0, bool needRoll = false) {
|
||||
const auto SERVERSOCKET = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
|
||||
auto t = timeval{.tv_sec = 5, .tv_usec = 0};
|
||||
setsockopt(SERVERSOCKET, SOL_SOCKET, SO_RCVTIMEO, &t, sizeof(struct timeval));
|
||||
|
||||
const auto ARGS = std::count(arg.begin(), arg.end(), ' ');
|
||||
|
||||
if (ARGS < minArgs) {
|
||||
log("Not enough arguments, expected at least " + minArgs);
|
||||
log(std::format("Not enough arguments in '{}', expected at least {}", arg, minArgs));
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -139,12 +183,17 @@ int request(std::string arg, int minArgs = 0) {
|
||||
return 4;
|
||||
}
|
||||
|
||||
if (needRoll)
|
||||
return rollingRead(SERVERSOCKET);
|
||||
|
||||
std::string reply = "";
|
||||
char buffer[8192] = {0};
|
||||
|
||||
sizeWritten = read(SERVERSOCKET, buffer, 8192);
|
||||
|
||||
if (sizeWritten < 0) {
|
||||
if (errno == EWOULDBLOCK)
|
||||
log("Hyprland IPC didn't respond in time\n");
|
||||
log("Couldn't read (5)");
|
||||
return 5;
|
||||
}
|
||||
@@ -238,12 +287,12 @@ void instancesRequest(bool json) {
|
||||
std::vector<SInstanceData> inst = instances();
|
||||
|
||||
if (!json) {
|
||||
for (auto& el : inst) {
|
||||
for (auto const& el : inst) {
|
||||
result += std::format("instance {}:\n\ttime: {}\n\tpid: {}\n\twl socket: {}\n\n", el.id, el.time, el.pid, el.wlSocket);
|
||||
}
|
||||
} else {
|
||||
result += '[';
|
||||
for (auto& el : inst) {
|
||||
for (auto const& el : inst) {
|
||||
result += std::format(R"#(
|
||||
{{
|
||||
"instance": "{}",
|
||||
@@ -270,12 +319,6 @@ std::deque<std::string> splitArgs(int argc, char** argv) {
|
||||
return result;
|
||||
}
|
||||
|
||||
bool isNumber(const std::string& str, bool allowfloat) {
|
||||
if (str.empty())
|
||||
return false;
|
||||
return std::ranges::all_of(str.begin(), str.end(), [&](char c) { return isdigit(c) != 0 || c == '-' || (allowfloat && c == '.'); });
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
bool parseArgs = true;
|
||||
|
||||
@@ -288,6 +331,7 @@ int main(int argc, char** argv) {
|
||||
std::string fullArgs = "";
|
||||
const auto ARGS = splitArgs(argc, argv);
|
||||
bool json = false;
|
||||
bool needRoll = false;
|
||||
std::string overrideInstance = "";
|
||||
|
||||
for (std::size_t i = 0; i < ARGS.size(); ++i) {
|
||||
@@ -307,6 +351,9 @@ int main(int argc, char** argv) {
|
||||
fullArgs += "a";
|
||||
} else if ((ARGS[i] == "-c" || ARGS[i] == "--config") && !fullArgs.contains("c")) {
|
||||
fullArgs += "c";
|
||||
} else if ((ARGS[i] == "-f" || ARGS[i] == "--follow") && !fullArgs.contains("f")) {
|
||||
fullArgs += "f";
|
||||
needRoll = true;
|
||||
} else if (ARGS[i] == "--batch") {
|
||||
fullRequest = "--batch ";
|
||||
} else if (ARGS[i] == "--instance" || ARGS[i] == "-i") {
|
||||
@@ -366,6 +413,11 @@ int main(int argc, char** argv) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (needRoll && !fullRequest.contains("/rollinglog")) {
|
||||
log("only 'rollinglog' command supports '--follow' option");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (overrideInstance.contains("_"))
|
||||
instanceSignature = overrideInstance;
|
||||
else if (!overrideInstance.empty()) {
|
||||
@@ -425,6 +477,8 @@ int main(int argc, char** argv) {
|
||||
exitStatus = request(fullRequest, 1);
|
||||
else if (fullRequest.contains("/--help"))
|
||||
std::cout << USAGE << std::endl;
|
||||
else if (fullRequest.contains("/rollinglog") && needRoll)
|
||||
exitStatus = request(fullRequest, 0, true);
|
||||
else {
|
||||
exitStatus = request(fullRequest);
|
||||
}
|
||||
|
@@ -1,7 +1,26 @@
|
||||
executable('hyprctl', 'main.cpp',
|
||||
install: true
|
||||
executable(
|
||||
'hyprctl',
|
||||
'main.cpp',
|
||||
dependencies: [
|
||||
dependency('hyprutils', version: '>= 0.1.1'),
|
||||
],
|
||||
install: true,
|
||||
)
|
||||
|
||||
install_data('hyprctl.bash', install_dir: join_paths(get_option('datadir'), 'bash-completion/completions'), install_tag: 'runtime', rename: 'hyprctl')
|
||||
install_data('hyprctl.fish', install_dir: join_paths(get_option('datadir'), 'fish/vendor_completions.d'), install_tag: 'runtime')
|
||||
install_data('hyprctl.zsh', install_dir: join_paths(get_option('datadir'), 'zsh/site-functions'), install_tag: 'runtime', rename: '_hyprctl')
|
||||
install_data(
|
||||
'hyprctl.bash',
|
||||
install_dir: join_paths(get_option('datadir'), 'bash-completion/completions'),
|
||||
install_tag: 'runtime',
|
||||
rename: 'hyprctl',
|
||||
)
|
||||
install_data(
|
||||
'hyprctl.fish',
|
||||
install_dir: join_paths(get_option('datadir'), 'fish/vendor_completions.d'),
|
||||
install_tag: 'runtime',
|
||||
)
|
||||
install_data(
|
||||
'hyprctl.zsh',
|
||||
install_dir: join_paths(get_option('datadir'), 'zsh/site-functions'),
|
||||
install_tag: 'runtime',
|
||||
rename: '_hyprctl',
|
||||
)
|
||||
|
@@ -4,4 +4,4 @@ Name: Hyprland
|
||||
URL: https://github.com/hyprwm/Hyprland
|
||||
Description: Hyprland header files
|
||||
Version: @HYPRLAND_VERSION@
|
||||
Cflags: -I${prefix} -I${prefix}/hyprland/protocols -I${prefix}/hyprland -I${prefix}/hyprland/wlr
|
||||
Cflags: -I${prefix} -I${prefix}/hyprland/protocols -I${prefix}/hyprland
|
||||
|
@@ -9,11 +9,11 @@ file(GLOB_RECURSE SRCFILES CONFIGURE_DEPENDS "src/*.cpp")
|
||||
|
||||
set(CMAKE_CXX_STANDARD 23)
|
||||
|
||||
pkg_check_modules(tomlplusplus REQUIRED IMPORTED_TARGET tomlplusplus)
|
||||
pkg_check_modules(deps REQUIRED IMPORTED_TARGET tomlplusplus hyprutils>=0.1.1)
|
||||
|
||||
add_executable(hyprpm ${SRCFILES})
|
||||
|
||||
target_link_libraries(hyprpm PUBLIC PkgConfig::tomlplusplus)
|
||||
target_link_libraries(hyprpm PUBLIC PkgConfig::deps)
|
||||
|
||||
# binary
|
||||
install(TARGETS hyprpm)
|
||||
|
@@ -1,5 +1,9 @@
|
||||
_hyprpm_cmd_0 () {
|
||||
hyprpm list | grep Plugin | awk '{print $4}'
|
||||
hyprpm list | awk '/Plugin/{print $4}'
|
||||
}
|
||||
|
||||
_hyprpm_cmd_1 () {
|
||||
hyprpm list | awk '/Repository/{print $4}' | sed 's/:$//'
|
||||
}
|
||||
|
||||
_hyprpm () {
|
||||
@@ -11,16 +15,13 @@ _hyprpm () {
|
||||
local words cword
|
||||
_get_comp_words_by_ref -n "$COMP_WORDBREAKS" words cword
|
||||
|
||||
local -a literals=("-n" "::=" "list" "disable" "--help" "update" "add" "--verbose" "-v" "--force" "remove" "enable" "--notify" "-h" "reload" "-f")
|
||||
|
||||
declare -a literals=(--no-shallow -n ::= disable list --help update add --verbose -v --force -s remove enable --notify -h reload -f)
|
||||
declare -A literal_transitions
|
||||
literal_transitions[0]="([9]=6 [2]=2 [7]=6 [8]=6 [4]=6 [10]=2 [11]=3 [5]=2 [13]=6 [3]=3 [14]=2 [15]=6 [6]=2)"
|
||||
literal_transitions[1]="([10]=2 [11]=3 [3]=3 [2]=2 [14]=2 [5]=2 [6]=2)"
|
||||
literal_transitions[4]="([1]=5)"
|
||||
literal_transitions[5]="([0]=6 [12]=6)"
|
||||
|
||||
declare -A match_anything_transitions
|
||||
match_anything_transitions=([3]=2 [2]=4 [0]=1 [1]=1)
|
||||
literal_transitions[0]="([0]=7 [3]=3 [4]=4 [8]=7 [9]=7 [6]=4 [7]=4 [11]=7 [5]=7 [10]=7 [12]=2 [13]=3 [15]=7 [16]=4 [17]=7)"
|
||||
literal_transitions[1]="([12]=2 [13]=3 [3]=3 [4]=4 [16]=4 [6]=4 [7]=4)"
|
||||
literal_transitions[5]="([2]=6)"
|
||||
literal_transitions[6]="([1]=7 [14]=7)"
|
||||
declare -A match_anything_transitions=([1]=1 [4]=5 [3]=4 [2]=4 [0]=1)
|
||||
declare -A subword_transitions
|
||||
|
||||
local state=0
|
||||
@@ -58,21 +59,9 @@ _hyprpm () {
|
||||
done
|
||||
|
||||
|
||||
local -a matches=()
|
||||
|
||||
local prefix="${words[$cword]}"
|
||||
|
||||
local shortest_suffix="$word"
|
||||
for ((i=0; i < ${#COMP_WORDBREAKS}; i++)); do
|
||||
local char="${COMP_WORDBREAKS:$i:1}"
|
||||
local candidate="${word##*$char}"
|
||||
if [[ ${#candidate} -lt ${#shortest_suffix} ]]; then
|
||||
shortest_suffix=$candidate
|
||||
fi
|
||||
done
|
||||
local superfluous_prefix=""
|
||||
if [[ "$shortest_suffix" != "$word" ]]; then
|
||||
local superfluous_prefix=${word%$shortest_suffix}
|
||||
fi
|
||||
|
||||
if [[ -v "literal_transitions[$state]" ]]; then
|
||||
local state_transitions_initializer=${literal_transitions[$state]}
|
||||
declare -A state_transitions
|
||||
@@ -81,25 +70,38 @@ _hyprpm () {
|
||||
for literal_id in "${!state_transitions[@]}"; do
|
||||
local literal="${literals[$literal_id]}"
|
||||
if [[ $literal = "${prefix}"* ]]; then
|
||||
local completion=${literal#"$superfluous_prefix"}
|
||||
COMPREPLY+=("$completion ")
|
||||
matches+=("$literal ")
|
||||
fi
|
||||
done
|
||||
fi
|
||||
declare -A commands
|
||||
commands=([3]=0)
|
||||
commands=([3]=0 [2]=1)
|
||||
if [[ -v "commands[$state]" ]]; then
|
||||
local command_id=${commands[$state]}
|
||||
local completions=()
|
||||
mapfile -t completions < <(_hyprpm_cmd_${command_id} "$prefix" | cut -f1)
|
||||
readarray -t completions < <(_hyprpm_cmd_${command_id} "$prefix" | cut -f1)
|
||||
for item in "${completions[@]}"; do
|
||||
if [[ $item = "${prefix}"* ]]; then
|
||||
COMPREPLY+=("$item")
|
||||
matches+=("$item")
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
|
||||
local shortest_suffix="$prefix"
|
||||
for ((i=0; i < ${#COMP_WORDBREAKS}; i++)); do
|
||||
local char="${COMP_WORDBREAKS:$i:1}"
|
||||
local candidate=${prefix##*$char}
|
||||
if [[ ${#candidate} -lt ${#shortest_suffix} ]]; then
|
||||
shortest_suffix=$candidate
|
||||
fi
|
||||
done
|
||||
local superfluous_prefix=""
|
||||
if [[ "$shortest_suffix" != "$prefix" ]]; then
|
||||
local superfluous_prefix=${prefix%$shortest_suffix}
|
||||
fi
|
||||
COMPREPLY=("${matches[@]#$superfluous_prefix}")
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
|
@@ -1,6 +1,11 @@
|
||||
function _hyprpm_1
|
||||
set 1 $argv[1]
|
||||
hyprpm list | grep Plugin | awk '{print $4}'
|
||||
hyprpm list | awk '/Plugin/{print $4}'
|
||||
end
|
||||
|
||||
function _hyprpm_2
|
||||
set 1 $argv[1]
|
||||
hyprpm list | awk '/Repository/{print $4}' | sed 's/:$//'
|
||||
end
|
||||
|
||||
function _hyprpm
|
||||
@@ -14,49 +19,51 @@ function _hyprpm
|
||||
set COMP_CWORD (count $COMP_WORDS)
|
||||
end
|
||||
|
||||
set --local literals "-n" "::=" "list" "disable" "--help" "update" "add" "--verbose" "-v" "--force" "remove" "enable" "--notify" "-h" "reload" "-f"
|
||||
set literals "--no-shallow" "-n" "::=" "disable" "list" "--help" "update" "add" "--verbose" "-v" "--force" "-s" "remove" "enable" "--notify" "-h" "reload" "-f"
|
||||
|
||||
set --local descriptions
|
||||
set descriptions[1] "Send a hyprland notification for important events (e.g. load fail)"
|
||||
set descriptions[3] "List all installed plugins"
|
||||
set descriptions
|
||||
set descriptions[1] "Disable shallow cloning of Hyprland sources"
|
||||
set descriptions[2] "Send a hyprland notification for important events (e.g. load fail)"
|
||||
set descriptions[4] "Unload a plugin"
|
||||
set descriptions[5] "Show help menu"
|
||||
set descriptions[6] "Check and update all plugins if needed"
|
||||
set descriptions[7] "Install a new plugin repository from git"
|
||||
set descriptions[8] "Enable too much loggin"
|
||||
set descriptions[5] "List all installed plugins"
|
||||
set descriptions[6] "Show help menu"
|
||||
set descriptions[7] "Check and update all plugins if needed"
|
||||
set descriptions[8] "Install a new plugin repository from git"
|
||||
set descriptions[9] "Enable too much loggin"
|
||||
set descriptions[10] "Force an operation ignoring checks (e.g. update -f)"
|
||||
set descriptions[11] "Remove a plugin repository"
|
||||
set descriptions[12] "Load a plugin"
|
||||
set descriptions[13] "Send a hyprland notification for important events (e.g. load fail)"
|
||||
set descriptions[14] "Show help menu"
|
||||
set descriptions[15] "Reload all plugins"
|
||||
set descriptions[16] "Force an operation ignoring checks (e.g. update -f)"
|
||||
set descriptions[10] "Enable too much loggin"
|
||||
set descriptions[11] "Force an operation ignoring checks (e.g. update -f)"
|
||||
set descriptions[12] "Disable shallow cloning of Hyprland sources"
|
||||
set descriptions[13] "Remove a plugin repository"
|
||||
set descriptions[14] "Load a plugin"
|
||||
set descriptions[15] "Send a hyprland notification for important events (e.g. load fail)"
|
||||
set descriptions[16] "Show help menu"
|
||||
set descriptions[17] "Reload all plugins"
|
||||
set descriptions[18] "Force an operation ignoring checks (e.g. update -f)"
|
||||
|
||||
set --local literal_transitions
|
||||
set literal_transitions[1] "set inputs 10 3 8 9 5 11 12 6 14 4 15 16 7; set tos 7 3 7 7 7 3 4 3 7 4 3 7 3"
|
||||
set literal_transitions[2] "set inputs 11 12 4 3 15 6 7; set tos 3 4 4 3 3 3 3"
|
||||
set literal_transitions[5] "set inputs 2; set tos 6"
|
||||
set literal_transitions[6] "set inputs 1 13; set tos 7 7"
|
||||
set literal_transitions
|
||||
set literal_transitions[1] "set inputs 1 4 5 9 10 7 8 12 6 11 13 14 16 17 18; set tos 8 4 5 8 8 5 5 8 8 8 3 4 8 5 8"
|
||||
set literal_transitions[2] "set inputs 13 14 4 5 17 7 8; set tos 3 4 4 5 5 5 5"
|
||||
set literal_transitions[6] "set inputs 3; set tos 7"
|
||||
set literal_transitions[7] "set inputs 2 15; set tos 8 8"
|
||||
|
||||
set --local match_anything_transitions_from 4 3 1 2
|
||||
set --local match_anything_transitions_to 3 5 2 2
|
||||
set match_anything_transitions_from 2 5 4 3 1
|
||||
set match_anything_transitions_to 2 6 5 5 2
|
||||
|
||||
set --local state 1
|
||||
set --local word_index 2
|
||||
set state 1
|
||||
set word_index 2
|
||||
while test $word_index -lt $COMP_CWORD
|
||||
set --local -- word $COMP_WORDS[$word_index]
|
||||
set -- word $COMP_WORDS[$word_index]
|
||||
|
||||
if set --query literal_transitions[$state] && test -n $literal_transitions[$state]
|
||||
set --local --erase inputs
|
||||
set --local --erase tos
|
||||
set --erase inputs
|
||||
set --erase tos
|
||||
eval $literal_transitions[$state]
|
||||
|
||||
if contains -- $word $literals
|
||||
set --local literal_matched 0
|
||||
set literal_matched 0
|
||||
for literal_id in (seq 1 (count $literals))
|
||||
if test $literals[$literal_id] = $word
|
||||
set --local index (contains --index -- $literal_id $inputs)
|
||||
set index (contains --index -- $literal_id $inputs)
|
||||
set state $tos[$index]
|
||||
set word_index (math $word_index + 1)
|
||||
set literal_matched 1
|
||||
@@ -70,7 +77,7 @@ function _hyprpm
|
||||
end
|
||||
|
||||
if set --query match_anything_transitions_from[$state] && test -n $match_anything_transitions_from[$state]
|
||||
set --local index (contains --index -- $state $match_anything_transitions_from)
|
||||
set index (contains --index -- $state $match_anything_transitions_from)
|
||||
set state $match_anything_transitions_to[$index]
|
||||
set word_index (math $word_index + 1)
|
||||
continue
|
||||
@@ -80,8 +87,8 @@ function _hyprpm
|
||||
end
|
||||
|
||||
if set --query literal_transitions[$state] && test -n $literal_transitions[$state]
|
||||
set --local --erase inputs
|
||||
set --local --erase tos
|
||||
set --erase inputs
|
||||
set --erase tos
|
||||
eval $literal_transitions[$state]
|
||||
for literal_id in $inputs
|
||||
if test -n $descriptions[$literal_id]
|
||||
@@ -92,14 +99,14 @@ function _hyprpm
|
||||
end
|
||||
end
|
||||
|
||||
set command_states 4
|
||||
set command_ids 1
|
||||
set command_states 4 3
|
||||
set command_ids 1 2
|
||||
if contains $state $command_states
|
||||
set --local index (contains --index $state $command_states)
|
||||
set --local function_id $command_ids[$index]
|
||||
set --local function_name _hyprpm_$function_id
|
||||
set --local --erase inputs
|
||||
set --local --erase tos
|
||||
set index (contains --index $state $command_states)
|
||||
set function_id $command_ids[$index]
|
||||
set function_name _hyprpm_$function_id
|
||||
set --erase inputs
|
||||
set --erase tos
|
||||
$function_name "$COMP_WORDS[$COMP_CWORD]"
|
||||
end
|
||||
|
||||
|
@@ -5,10 +5,11 @@ hyprpm [<FLAGS>]... <ARGUMENT>
|
||||
| (--help | -h) "Show help menu"
|
||||
| (--verbose | -v) "Enable too much loggin"
|
||||
| (--force | -f) "Force an operation ignoring checks (e.g. update -f)"
|
||||
| (--no-shallow | -s) "Disable shallow cloning of Hyprland sources"
|
||||
;
|
||||
|
||||
<ARGUMENT> ::= (add) "Install a new plugin repository from git"
|
||||
| (remove) "Remove a plugin repository"
|
||||
| (remove <PLUGIN_REPOS>) "Remove a plugin repository"
|
||||
| (update) "Check and update all plugins if needed"
|
||||
| (list) "List all installed plugins"
|
||||
| (enable <PLUGINS>) "Load a plugin"
|
||||
@@ -16,4 +17,5 @@ hyprpm [<FLAGS>]... <ARGUMENT>
|
||||
| (reload) "Reload all plugins"
|
||||
;
|
||||
|
||||
<PLUGINS> ::= {{{ hyprpm list | grep Plugin | awk '{print $4}' }}};
|
||||
<PLUGINS> ::= {{{ hyprpm list | awk '/Plugin/{print $4}' }}};
|
||||
<PLUGIN_REPOS> ::= {{{ hyprpm list | awk '/Repository/{print $4}' | sed 's/:$//' }}};
|
||||
|
@@ -1,37 +1,43 @@
|
||||
#compdef hyprpm
|
||||
|
||||
_hyprpm_cmd_0 () {
|
||||
hyprpm list | grep Plugin | awk '{print $4}'
|
||||
hyprpm list | awk '/Plugin/{print $4}'
|
||||
}
|
||||
|
||||
_hyprpm_cmd_1 () {
|
||||
hyprpm list | awk '/Repository/{print $4}' | sed 's/:$//'
|
||||
}
|
||||
|
||||
_hyprpm () {
|
||||
local -a literals=("-n" "::=" "list" "disable" "--help" "update" "add" "--verbose" "-v" "--force" "remove" "enable" "--notify" "-h" "reload" "-f")
|
||||
local -a literals=("--no-shallow" "-n" "::=" "disable" "list" "--help" "update" "add" "--verbose" "-v" "--force" "-s" "remove" "enable" "--notify" "-h" "reload" "-f")
|
||||
|
||||
local -A descriptions
|
||||
descriptions[1]="Send a hyprland notification for important events (e.g. load fail)"
|
||||
descriptions[3]="List all installed plugins"
|
||||
descriptions[1]="Disable shallow cloning of Hyprland sources"
|
||||
descriptions[2]="Send a hyprland notification for important events (e.g. load fail)"
|
||||
descriptions[4]="Unload a plugin"
|
||||
descriptions[5]="Show help menu"
|
||||
descriptions[6]="Check and update all plugins if needed"
|
||||
descriptions[7]="Install a new plugin repository from git"
|
||||
descriptions[8]="Enable too much loggin"
|
||||
descriptions[5]="List all installed plugins"
|
||||
descriptions[6]="Show help menu"
|
||||
descriptions[7]="Check and update all plugins if needed"
|
||||
descriptions[8]="Install a new plugin repository from git"
|
||||
descriptions[9]="Enable too much loggin"
|
||||
descriptions[10]="Force an operation ignoring checks (e.g. update -f)"
|
||||
descriptions[11]="Remove a plugin repository"
|
||||
descriptions[12]="Load a plugin"
|
||||
descriptions[13]="Send a hyprland notification for important events (e.g. load fail)"
|
||||
descriptions[14]="Show help menu"
|
||||
descriptions[15]="Reload all plugins"
|
||||
descriptions[16]="Force an operation ignoring checks (e.g. update -f)"
|
||||
descriptions[10]="Enable too much loggin"
|
||||
descriptions[11]="Force an operation ignoring checks (e.g. update -f)"
|
||||
descriptions[12]="Disable shallow cloning of Hyprland sources"
|
||||
descriptions[13]="Remove a plugin repository"
|
||||
descriptions[14]="Load a plugin"
|
||||
descriptions[15]="Send a hyprland notification for important events (e.g. load fail)"
|
||||
descriptions[16]="Show help menu"
|
||||
descriptions[17]="Reload all plugins"
|
||||
descriptions[18]="Force an operation ignoring checks (e.g. update -f)"
|
||||
|
||||
local -A literal_transitions
|
||||
literal_transitions[1]="([10]=7 [3]=3 [8]=7 [9]=7 [5]=7 [11]=3 [12]=4 [6]=3 [14]=7 [4]=4 [15]=3 [16]=7 [7]=3)"
|
||||
literal_transitions[2]="([11]=3 [12]=4 [4]=4 [3]=3 [15]=3 [6]=3 [7]=3)"
|
||||
literal_transitions[5]="([2]=6)"
|
||||
literal_transitions[6]="([1]=7 [13]=7)"
|
||||
literal_transitions[1]="([1]=8 [4]=4 [5]=5 [9]=8 [10]=8 [7]=5 [8]=5 [12]=8 [6]=8 [11]=8 [13]=3 [14]=4 [16]=8 [17]=5 [18]=8)"
|
||||
literal_transitions[2]="([13]=3 [14]=4 [4]=4 [5]=5 [17]=5 [7]=5 [8]=5)"
|
||||
literal_transitions[6]="([3]=7)"
|
||||
literal_transitions[7]="([2]=8 [15]=8)"
|
||||
|
||||
local -A match_anything_transitions
|
||||
match_anything_transitions=([4]=3 [3]=5 [1]=2 [2]=2)
|
||||
match_anything_transitions=([2]=2 [5]=6 [4]=5 [3]=5 [1]=2)
|
||||
|
||||
declare -A subword_transitions
|
||||
|
||||
@@ -91,7 +97,7 @@ _hyprpm () {
|
||||
fi
|
||||
done
|
||||
fi
|
||||
local -A commands=([4]=0)
|
||||
local -A commands=([4]=0 [3]=1)
|
||||
|
||||
if [[ -v "commands[$state]" ]]; then
|
||||
local command_id=${commands[$state]}
|
||||
|
@@ -49,7 +49,7 @@ void DataState::addNewPluginRepo(const SPluginRepository& repo) {
|
||||
{"rev", repo.rev}
|
||||
}}
|
||||
};
|
||||
for (auto& p : repo.plugins) {
|
||||
for (auto const& p : repo.plugins) {
|
||||
// copy .so to the good place
|
||||
if (std::filesystem::exists(p.filename))
|
||||
std::filesystem::copy_file(p.filename, PATH + "/" + p.name + ".so");
|
||||
|
@@ -6,7 +6,7 @@ CManifest::CManifest(const eManifestType type, const std::string& path) {
|
||||
auto manifest = toml::parse_file(path);
|
||||
|
||||
if (type == MANIFEST_HYPRLOAD) {
|
||||
for (auto& [key, val] : manifest) {
|
||||
for (auto const& [key, val] : manifest) {
|
||||
if (key.str().ends_with(".build"))
|
||||
continue;
|
||||
|
||||
@@ -63,7 +63,7 @@ CManifest::CManifest(const eManifestType type, const std::string& path) {
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& [key, val] : manifest) {
|
||||
for (auto const& [key, val] : manifest) {
|
||||
if (key.str() == "repository")
|
||||
continue;
|
||||
|
||||
|
@@ -19,30 +19,15 @@
|
||||
|
||||
#include <toml++/toml.hpp>
|
||||
|
||||
static std::string removeBeginEndSpacesTabs(std::string str) {
|
||||
if (str.empty())
|
||||
return str;
|
||||
|
||||
int countBefore = 0;
|
||||
while (str[countBefore] == ' ' || str[countBefore] == '\t') {
|
||||
countBefore++;
|
||||
}
|
||||
|
||||
int countAfter = 0;
|
||||
while ((int)str.length() - countAfter - 1 >= 0 && (str[str.length() - countAfter - 1] == ' ' || str[str.length() - 1 - countAfter] == '\t')) {
|
||||
countAfter++;
|
||||
}
|
||||
|
||||
str = str.substr(countBefore, str.length() - countBefore - countAfter);
|
||||
|
||||
return str;
|
||||
}
|
||||
#include <hyprutils/string/String.hpp>
|
||||
using namespace Hyprutils::String;
|
||||
|
||||
static std::string execAndGet(std::string cmd) {
|
||||
cmd += " 2>&1";
|
||||
std::array<char, 128> buffer;
|
||||
std::string result;
|
||||
const std::unique_ptr<FILE, decltype(&pclose)> pipe(popen(cmd.c_str(), "r"), pclose);
|
||||
using PcloseType = int (*)(FILE*);
|
||||
const std::unique_ptr<FILE, PcloseType> pipe(popen(cmd.c_str(), "r"), static_cast<PcloseType>(pclose));
|
||||
if (!pipe)
|
||||
return "";
|
||||
|
||||
@@ -187,6 +172,9 @@ bool CPluginManager::addNewPluginRepo(const std::string& url, const std::string&
|
||||
std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " Could not check out revision " << rev << ". shell returned:\n" << ret << "\n";
|
||||
return false;
|
||||
}
|
||||
ret = execAndGet("git -C " + m_szWorkingPluginDirectory + " submodule update --init");
|
||||
if (m_bVerbose)
|
||||
std::cout << Colors::BLUE << "[v] " << Colors::RESET << "git submodule update --init returned: " << ret << "\n";
|
||||
}
|
||||
|
||||
progress.m_iSteps = 1;
|
||||
@@ -216,9 +204,9 @@ bool CPluginManager::addNewPluginRepo(const std::string& url, const std::string&
|
||||
|
||||
progress.m_iSteps = 2;
|
||||
progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " parsed manifest, found " + std::to_string(pManifest->m_vPlugins.size()) + " plugins:");
|
||||
for (auto& pl : pManifest->m_vPlugins) {
|
||||
for (auto const& pl : pManifest->m_vPlugins) {
|
||||
std::string message = std::string{Colors::RESET} + " → " + pl.name + " by ";
|
||||
for (auto& a : pl.authors) {
|
||||
for (auto const& a : pl.authors) {
|
||||
message += a + ", ";
|
||||
}
|
||||
if (pl.authors.size() > 0) {
|
||||
@@ -234,13 +222,19 @@ bool CPluginManager::addNewPluginRepo(const std::string& url, const std::string&
|
||||
|
||||
progress.printMessageAbove(std::string{Colors::RESET} + " → Manifest has " + std::to_string(pManifest->m_sRepository.commitPins.size()) + " pins, checking");
|
||||
|
||||
for (auto& [hl, plugin] : pManifest->m_sRepository.commitPins) {
|
||||
for (auto const& [hl, plugin] : pManifest->m_sRepository.commitPins) {
|
||||
if (hl != HLVER.hash)
|
||||
continue;
|
||||
|
||||
progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " commit pin " + plugin + " matched hl, resetting");
|
||||
|
||||
execAndGet("cd " + m_szWorkingPluginDirectory + " && git reset --hard --recurse-submodules " + plugin);
|
||||
|
||||
ret = execAndGet("git -C " + m_szWorkingPluginDirectory + " submodule update --init");
|
||||
if (m_bVerbose)
|
||||
std::cout << Colors::BLUE << "[v] " << Colors::RESET << "git submodule update --init returned: " << ret << "\n";
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -270,7 +264,7 @@ bool CPluginManager::addNewPluginRepo(const std::string& url, const std::string&
|
||||
|
||||
progress.printMessageAbove(std::string{Colors::RESET} + " → Building " + p.name);
|
||||
|
||||
for (auto& bs : p.buildSteps) {
|
||||
for (auto const& bs : p.buildSteps) {
|
||||
std::string cmd = std::format("cd {} && PKG_CONFIG_PATH=\"{}/share/pkgconfig\" {}", m_szWorkingPluginDirectory, DataState::getHeadersPath(), bs);
|
||||
out += " -> " + cmd + "\n" + execAndGet(cmd) + "\n";
|
||||
}
|
||||
@@ -305,7 +299,7 @@ bool CPluginManager::addNewPluginRepo(const std::string& url, const std::string&
|
||||
repo.url = url;
|
||||
repo.rev = rev;
|
||||
repo.hash = repohash;
|
||||
for (auto& p : pManifest->m_vPlugins) {
|
||||
for (auto const& p : pManifest->m_vPlugins) {
|
||||
repo.plugins.push_back(SPlugin{p.name, m_szWorkingPluginDirectory + "/" + p.output, false, p.failed});
|
||||
}
|
||||
DataState::addNewPluginRepo(repo);
|
||||
@@ -371,10 +365,10 @@ eHeadersErrors CPluginManager::headersValid() {
|
||||
else
|
||||
headers = "";
|
||||
|
||||
if (PATH.ends_with("protocols") || PATH.ends_with("wlroots-hyprland"))
|
||||
if (PATH.ends_with("protocols"))
|
||||
continue;
|
||||
|
||||
verHeader = removeBeginEndSpacesTabs(PATH.substr(2)) + "/hyprland/src/version.h";
|
||||
verHeader = trim(PATH.substr(2)) + "/hyprland/src/version.h";
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -442,12 +436,12 @@ bool CPluginManager::updateHeaders(bool force) {
|
||||
|
||||
progress.printMessageAbove(std::string{Colors::YELLOW} + "!" + Colors::RESET + " Cloning https://github.com/hyprwm/hyprland, this might take a moment.");
|
||||
|
||||
const bool bShallow = HLVER.branch == "main" || HLVER.branch == "";
|
||||
const bool bShallow = (HLVER.branch == "main" || HLVER.branch == "") && !m_bNoShallow;
|
||||
|
||||
// let us give a bit of leg-room for shallowing
|
||||
// due to timezones, etc.
|
||||
const std::string SHALLOW_DATE =
|
||||
removeBeginEndSpacesTabs(HLVER.date).empty() ? "" : execAndGet("LC_TIME=\"en_US.UTF-8\" date --date='" + HLVER.date + " - 1 weeks' '+\%a \%b \%d \%H:\%M:\%S \%Y'");
|
||||
trim(HLVER.date).empty() ? "" : execAndGet("LC_TIME=\"en_US.UTF-8\" date --date='" + HLVER.date + " - 1 weeks' '+\%a \%b \%d \%H:\%M:\%S \%Y'");
|
||||
|
||||
if (m_bVerbose && bShallow)
|
||||
progress.printMessageAbove(std::string{Colors::BLUE} + "[v] " + Colors::RESET + "will shallow since: " + SHALLOW_DATE);
|
||||
@@ -470,12 +464,22 @@ bool CPluginManager::updateHeaders(bool force) {
|
||||
progress.m_szCurrentMessage = "Checking out sources";
|
||||
progress.print();
|
||||
|
||||
ret = execAndGet("cd " + WORKINGDIR + " && git checkout " + HLVER.branch + " 2>&1");
|
||||
if (m_bVerbose)
|
||||
progress.printMessageAbove(std::string{Colors::BLUE} + "[v] " + Colors::RESET + "will run: " + "cd " + WORKINGDIR + " && git checkout " + HLVER.hash + " 2>&1");
|
||||
|
||||
ret = execAndGet("cd " + WORKINGDIR + " && git checkout " + HLVER.hash + " 2>&1");
|
||||
|
||||
if (ret.contains("fatal: unable to read tree")) {
|
||||
std::cerr << "\n"
|
||||
<< Colors::RED << "✖" << Colors::RESET
|
||||
<< " Could not checkout the running Hyprland commit. If you are on -git, try updating.\nYou can also try re-running hyprpm update with --no-shallow.\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_bVerbose)
|
||||
progress.printMessageAbove(std::string{Colors::BLUE} + "[v] " + Colors::RESET + "git returned (co): " + ret);
|
||||
|
||||
ret = execAndGet("cd " + WORKINGDIR + " && git rm subprojects/tracy && git submodule update --init 2>&1 && git reset --hard --recurse-submodules " + HLVER.hash);
|
||||
ret = execAndGet("cd " + WORKINGDIR + " ; git rm subprojects/tracy ; git submodule update --init 2>&1 ; git reset --hard --recurse-submodules " + HLVER.hash);
|
||||
|
||||
if (m_bVerbose)
|
||||
progress.printMessageAbove(std::string{Colors::BLUE} + "[v] " + Colors::RESET + "git returned (rs): " + ret);
|
||||
@@ -495,21 +499,19 @@ bool CPluginManager::updateHeaders(bool force) {
|
||||
if (m_bVerbose)
|
||||
progress.printMessageAbove(std::string{Colors::BLUE} + "[v] " + Colors::RESET + "cmake returned: " + ret);
|
||||
|
||||
if (ret.contains("required packages were not found")) {
|
||||
if (ret.contains("CMake Error at")) {
|
||||
// missing deps, let the user know.
|
||||
std::string missing = ret.substr(ret.find("The following required packages were not found:"));
|
||||
missing = missing.substr(0, missing.find("Call Stack"));
|
||||
std::string missing = ret.substr(ret.find("CMake Error at"));
|
||||
missing = ret.substr(ret.find_first_of('\n') + 1);
|
||||
missing = missing.substr(0, missing.find("-- Configuring incomplete"));
|
||||
missing = missing.substr(0, missing.find_last_of('\n'));
|
||||
|
||||
std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " Could not configure the hyprland source, cmake complained:\n" << missing << "\n";
|
||||
std::cerr << "\n"
|
||||
<< Colors::RED << "✖" << Colors::RESET << " Could not configure the hyprland source, cmake complained:\n"
|
||||
<< missing << "\n\nThis likely means that you are missing the above dependencies or they are out of date.\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
// le hack. Wlroots has to generate its build/include
|
||||
ret = execAndGet("cd " + WORKINGDIR + "/subprojects/wlroots-hyprland && meson setup -Drenderers=gles2 -Dexamples=false build");
|
||||
if (m_bVerbose)
|
||||
progress.printMessageAbove(std::string{Colors::BLUE} + "[v] " + Colors::RESET + "meson returned: " + ret);
|
||||
|
||||
progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " configured Hyprland");
|
||||
progress.m_iSteps = 4;
|
||||
progress.m_szCurrentMessage = "Installing sources";
|
||||
@@ -537,7 +539,8 @@ bool CPluginManager::updateHeaders(bool force) {
|
||||
|
||||
std::cout << "\n";
|
||||
} else {
|
||||
progress.printMessageAbove(std::string{Colors::RED} + "✖" + Colors::RESET + " failed to install headers with error code " + std::to_string((int)HEADERSVALID));
|
||||
progress.printMessageAbove(std::string{Colors::RED} + "✖" + Colors::RESET + " failed to install headers with error code " + std::to_string((int)HEADERSVALID) + " (" +
|
||||
headerErrorShort(HEADERSVALID) + ")");
|
||||
progress.m_iSteps = 5;
|
||||
progress.m_szCurrentMessage = "Failed";
|
||||
progress.print();
|
||||
@@ -576,7 +579,7 @@ bool CPluginManager::updatePlugins(bool forceUpdateAll) {
|
||||
const std::string USERNAME = getpwuid(getuid())->pw_name;
|
||||
m_szWorkingPluginDirectory = "/tmp/hyprpm/" + USERNAME;
|
||||
|
||||
for (auto& repo : REPOS) {
|
||||
for (auto const& repo : REPOS) {
|
||||
bool update = forceUpdateAll;
|
||||
|
||||
progress.m_iSteps++;
|
||||
@@ -655,7 +658,7 @@ bool CPluginManager::updatePlugins(bool forceUpdateAll) {
|
||||
|
||||
progress.printMessageAbove(std::string{Colors::RESET} + " → Manifest has " + std::to_string(pManifest->m_sRepository.commitPins.size()) + " pins, checking");
|
||||
|
||||
for (auto& [hl, plugin] : pManifest->m_sRepository.commitPins) {
|
||||
for (auto const& [hl, plugin] : pManifest->m_sRepository.commitPins) {
|
||||
if (hl != HLVER.hash)
|
||||
continue;
|
||||
|
||||
@@ -676,7 +679,7 @@ bool CPluginManager::updatePlugins(bool forceUpdateAll) {
|
||||
|
||||
progress.printMessageAbove(std::string{Colors::RESET} + " → Building " + p.name);
|
||||
|
||||
for (auto& bs : p.buildSteps) {
|
||||
for (auto const& bs : p.buildSteps) {
|
||||
std::string cmd = std::format("cd {} && PKG_CONFIG_PATH=\"{}/share/pkgconfig\" {}", m_szWorkingPluginDirectory, DataState::getHeadersPath(), bs);
|
||||
out += " -> " + cmd + "\n" + execAndGet(cmd) + "\n";
|
||||
}
|
||||
@@ -706,7 +709,7 @@ bool CPluginManager::updatePlugins(bool forceUpdateAll) {
|
||||
if (repohash.length() > 0)
|
||||
repohash.pop_back();
|
||||
newrepo.hash = repohash;
|
||||
for (auto& p : pManifest->m_vPlugins) {
|
||||
for (auto const& p : pManifest->m_vPlugins) {
|
||||
const auto OLDPLUGINIT = std::find_if(repo.plugins.begin(), repo.plugins.end(), [&](const auto& other) { return other.name == p.name; });
|
||||
newrepo.plugins.push_back(SPlugin{p.name, m_szWorkingPluginDirectory + "/" + p.output, OLDPLUGINIT != repo.plugins.end() ? OLDPLUGINIT->enabled : false});
|
||||
}
|
||||
@@ -791,8 +794,8 @@ ePluginLoadStateReturn CPluginManager::ensurePluginsLoadState() {
|
||||
const auto REPOS = DataState::getAllRepositories();
|
||||
|
||||
auto enabled = [REPOS](const std::string& plugin) -> bool {
|
||||
for (auto& r : REPOS) {
|
||||
for (auto& p : r.plugins) {
|
||||
for (auto const& r : REPOS) {
|
||||
for (auto const& p : r.plugins) {
|
||||
if (p.name == plugin && p.enabled)
|
||||
return true;
|
||||
}
|
||||
@@ -802,8 +805,8 @@ ePluginLoadStateReturn CPluginManager::ensurePluginsLoadState() {
|
||||
};
|
||||
|
||||
auto repoForName = [REPOS](const std::string& name) -> std::string {
|
||||
for (auto& r : REPOS) {
|
||||
for (auto& p : r.plugins) {
|
||||
for (auto const& r : REPOS) {
|
||||
for (auto const& p : r.plugins) {
|
||||
if (p.name == name)
|
||||
return r.name;
|
||||
}
|
||||
@@ -813,7 +816,7 @@ ePluginLoadStateReturn CPluginManager::ensurePluginsLoadState() {
|
||||
};
|
||||
|
||||
// unload disabled plugins
|
||||
for (auto& p : loadedPlugins) {
|
||||
for (auto const& p : loadedPlugins) {
|
||||
if (!enabled(p)) {
|
||||
// unload
|
||||
loadUnloadPlugin(HYPRPMPATH + repoForName(p) + "/" + p + ".so", false);
|
||||
@@ -822,8 +825,8 @@ ePluginLoadStateReturn CPluginManager::ensurePluginsLoadState() {
|
||||
}
|
||||
|
||||
// load enabled plugins
|
||||
for (auto& r : REPOS) {
|
||||
for (auto& p : r.plugins) {
|
||||
for (auto const& r : REPOS) {
|
||||
for (auto const& p : r.plugins) {
|
||||
if (!p.enabled)
|
||||
continue;
|
||||
|
||||
@@ -852,10 +855,10 @@ bool CPluginManager::loadUnloadPlugin(const std::string& path, bool load) {
|
||||
void CPluginManager::listAllPlugins() {
|
||||
const auto REPOS = DataState::getAllRepositories();
|
||||
|
||||
for (auto& r : REPOS) {
|
||||
for (auto const& r : REPOS) {
|
||||
std::cout << std::string{Colors::RESET} + " → Repository " + r.name + ":\n";
|
||||
|
||||
for (auto& p : r.plugins) {
|
||||
for (auto const& p : r.plugins) {
|
||||
|
||||
std::cout << std::string{Colors::RESET} + " │ Plugin " + p.name;
|
||||
|
||||
@@ -888,10 +891,22 @@ std::string CPluginManager::headerError(const eHeadersErrors err) {
|
||||
return std::string{Colors::RED} + "✖" + Colors::RESET + " Unknown header error. Please run hyprpm update to fix those.\n";
|
||||
}
|
||||
|
||||
std::string CPluginManager::headerErrorShort(const eHeadersErrors err) {
|
||||
switch (err) {
|
||||
case HEADERS_CORRUPTED: return "Headers corrupted";
|
||||
case HEADERS_MISMATCHED: return "Headers version mismatched";
|
||||
case HEADERS_NOT_HYPRLAND: return "Not running on Hyprland";
|
||||
case HEADERS_MISSING: return "Headers missing";
|
||||
case HEADERS_DUPLICATED: return "Headers duplicated";
|
||||
default: break;
|
||||
}
|
||||
return "?";
|
||||
}
|
||||
|
||||
bool CPluginManager::hasDeps() {
|
||||
std::vector<std::string> deps = {"meson", "cpio", "cmake"};
|
||||
for (auto& d : deps) {
|
||||
if (!execAndGet("which " + d + " 2>&1").contains("/"))
|
||||
std::vector<std::string> deps = {"meson", "cpio", "cmake", "pkg-config"};
|
||||
for (auto const& d : deps) {
|
||||
if (!execAndGet("command -v " + d).contains("/"))
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@@ -59,12 +59,14 @@ class CPluginManager {
|
||||
bool hasDeps();
|
||||
|
||||
bool m_bVerbose = false;
|
||||
bool m_bNoShallow = false;
|
||||
|
||||
// will delete recursively if exists!!
|
||||
bool createSafeDirectory(const std::string& path);
|
||||
|
||||
private:
|
||||
std::string headerError(const eHeadersErrors err);
|
||||
std::string headerErrorShort(const eHeadersErrors err);
|
||||
|
||||
std::string m_szWorkingPluginDirectory = "";
|
||||
};
|
||||
|
@@ -26,6 +26,7 @@ const std::string HELP = R"#(┏ hyprpm, a Hyprland Plugin Manager
|
||||
┣ --help | -h → Show this menu
|
||||
┣ --verbose | -v → Enable too much logging
|
||||
┣ --force | -f → Force an operation ignoring checks (e.g. update -f)
|
||||
┣ --no-shallow | -s → Disable shallow cloning of Hyprland sources
|
||||
┗
|
||||
)#";
|
||||
|
||||
@@ -41,7 +42,7 @@ int main(int argc, char** argv, char** envp) {
|
||||
}
|
||||
|
||||
std::vector<std::string> command;
|
||||
bool notify = false, verbose = false, force = false;
|
||||
bool notify = false, verbose = false, force = false, noShallow = false;
|
||||
|
||||
for (int i = 1; i < argc; ++i) {
|
||||
if (ARGS[i].starts_with("-")) {
|
||||
@@ -52,6 +53,8 @@ int main(int argc, char** argv, char** envp) {
|
||||
notify = true;
|
||||
} else if (ARGS[i] == "--verbose" || ARGS[i] == "-v") {
|
||||
verbose = true;
|
||||
} else if (ARGS[i] == "--no-shallow" || ARGS[i] == "-s") {
|
||||
noShallow = true;
|
||||
} else if (ARGS[i] == "--force" || ARGS[i] == "-f") {
|
||||
force = true;
|
||||
std::cout << Colors::RED << "!" << Colors::RESET << " Using --force, I hope you know what you are doing.\n";
|
||||
@@ -71,6 +74,7 @@ int main(int argc, char** argv, char** envp) {
|
||||
|
||||
g_pPluginManager = std::make_unique<CPluginManager>();
|
||||
g_pPluginManager->m_bVerbose = verbose;
|
||||
g_pPluginManager->m_bNoShallow = noShallow;
|
||||
|
||||
if (command[0] == "add") {
|
||||
if (command.size() < 2) {
|
||||
|
@@ -1,14 +1,31 @@
|
||||
globber = run_command('sh', '-c', 'find . -name "*.cpp" | sort', check: true)
|
||||
src = globber.stdout().strip().split('\n')
|
||||
|
||||
executable('hyprpm', src,
|
||||
executable(
|
||||
'hyprpm',
|
||||
src,
|
||||
dependencies: [
|
||||
dependency('hyprutils', version: '>= 0.1.1'),
|
||||
dependency('threads'),
|
||||
dependency('tomlplusplus')
|
||||
dependency('tomlplusplus'),
|
||||
],
|
||||
install : true
|
||||
install: true,
|
||||
)
|
||||
|
||||
install_data('../hyprpm.bash', install_dir: join_paths(get_option('datadir'), 'bash-completion/completions'), install_tag: 'runtime', rename: 'hyprpm')
|
||||
install_data('../hyprpm.fish', install_dir: join_paths(get_option('datadir'), 'fish/vendor_completions.d'), install_tag: 'runtime')
|
||||
install_data('../hyprpm.zsh', install_dir: join_paths(get_option('datadir'), 'zsh/site-functions'), install_tag: 'runtime', rename: '_hyprpm')
|
||||
install_data(
|
||||
'../hyprpm.bash',
|
||||
install_dir: join_paths(get_option('datadir'), 'bash-completion/completions'),
|
||||
install_tag: 'runtime',
|
||||
rename: 'hyprpm',
|
||||
)
|
||||
install_data(
|
||||
'../hyprpm.fish',
|
||||
install_dir: join_paths(get_option('datadir'), 'fish/vendor_completions.d'),
|
||||
install_tag: 'runtime',
|
||||
)
|
||||
install_data(
|
||||
'../hyprpm.zsh',
|
||||
install_dir: join_paths(get_option('datadir'), 'zsh/site-functions'),
|
||||
install_tag: 'runtime',
|
||||
rename: '_hyprpm',
|
||||
)
|
||||
|
50
meson.build
@@ -1,31 +1,38 @@
|
||||
project('Hyprland', 'cpp', 'c',
|
||||
version : run_command('jq', '-r', '.version', join_paths(meson.source_root(), 'props.json'), check: true).stdout().strip(),
|
||||
default_options : [
|
||||
project(
|
||||
'Hyprland',
|
||||
'cpp',
|
||||
'c',
|
||||
version: run_command('cat', join_paths(meson.project_source_root(), 'VERSION'), check: true).stdout().strip(),
|
||||
default_options: [
|
||||
'warning_level=2',
|
||||
'default_library=static',
|
||||
'optimization=3',
|
||||
'buildtype=release',
|
||||
'debug=false',
|
||||
'cpp_std=c++23',
|
||||
])
|
||||
'cpp_std=c++26',
|
||||
],
|
||||
)
|
||||
|
||||
datarootdir = '-DDATAROOTDIR="' + get_option('prefix') / get_option('datadir') + '"'
|
||||
add_project_arguments(
|
||||
[
|
||||
'-Wno-unused-parameter',
|
||||
'-Wno-unused-value',
|
||||
'-Wno-missing-field-initializers',
|
||||
'-Wno-narrowing',
|
||||
'-Wno-pointer-arith',
|
||||
'-Wno-pointer-arith', datarootdir,
|
||||
],
|
||||
language: 'cpp')
|
||||
language: 'cpp',
|
||||
)
|
||||
|
||||
cpp_compiler = meson.get_compiler('cpp')
|
||||
if cpp_compiler.check_header('execinfo.h')
|
||||
add_project_arguments('-DHAS_EXECINFO', language: 'cpp')
|
||||
endif
|
||||
|
||||
wlroots = subproject('wlroots-hyprland', default_options: ['examples=false', 'renderers=gles2'])
|
||||
have_xwlr = wlroots.get_variable('features').get('xwayland')
|
||||
aquamarine = dependency('aquamarine')
|
||||
add_project_arguments(['-DAQUAMARINE_VERSION="@0@"'.format(aquamarine.version())], language: 'cpp')
|
||||
|
||||
xcb_dep = dependency('xcb', required: get_option('xwayland'))
|
||||
xcb_composite_dep = dependency('xcb-composite', required: get_option('xwayland'))
|
||||
xcb_errors_dep = dependency('xcb-errors', required: get_option('xwayland'))
|
||||
@@ -34,22 +41,16 @@ xcb_render_dep = dependency('xcb-render', required: get_option('xwayland'))
|
||||
xcb_res_dep = dependency('xcb-res', required: get_option('xwayland'))
|
||||
xcb_xfixes_dep = dependency('xcb-xfixes', required: get_option('xwayland'))
|
||||
|
||||
cmake = import('cmake')
|
||||
udis = cmake.subproject('udis86')
|
||||
udis86 = udis.dependency('libudis86')
|
||||
gio_dep = dependency('gio-2.0', required: true)
|
||||
|
||||
if get_option('xwayland').enabled() and not have_xwlr
|
||||
error('Cannot enable Xwayland in Hyprland: wlroots has been built without Xwayland support')
|
||||
endif
|
||||
have_xwayland = xcb_dep.found() and have_xwlr
|
||||
|
||||
if not have_xwayland
|
||||
if not xcb_dep.found()
|
||||
add_project_arguments('-DNO_XWAYLAND', language: 'cpp')
|
||||
endif
|
||||
|
||||
backtrace_dep = cpp_compiler.find_library('execinfo', required: false)
|
||||
epoll_dep = dependency('epoll-shim', required: false) # timerfd on BSDs
|
||||
|
||||
# Handle options
|
||||
if get_option('systemd').enabled()
|
||||
add_project_arguments('-DUSES_SYSTEMD', language: 'cpp')
|
||||
endif
|
||||
@@ -62,14 +63,22 @@ if get_option('buildtype') == 'debug'
|
||||
add_project_arguments('-DHYPRLAND_DEBUG', language: 'cpp')
|
||||
endif
|
||||
|
||||
version_h = run_command('sh', '-c', 'scripts/generateVersion.sh', check: true)
|
||||
# Generate hyprland version and populate version.h
|
||||
run_command('sh', '-c', 'scripts/generateVersion.sh', check: true)
|
||||
|
||||
# Install headers
|
||||
globber = run_command('find', 'src', '-name', '*.h*', check: true)
|
||||
headers = globber.stdout().strip().split('\n')
|
||||
foreach file : headers
|
||||
install_headers(file, subdir: 'hyprland', preserve_path: true)
|
||||
endforeach
|
||||
|
||||
tracy = dependency('tracy', static: true, required: get_option('tracy_enable'))
|
||||
|
||||
if get_option('tracy_enable') and get_option('buildtype') != 'debugoptimized'
|
||||
warning('Profiling builds should set -- buildtype = debugoptimized')
|
||||
endif
|
||||
|
||||
subdir('protocols')
|
||||
subdir('src')
|
||||
subdir('hyprctl')
|
||||
@@ -78,6 +87,7 @@ subdir('assets')
|
||||
subdir('example')
|
||||
subdir('docs')
|
||||
|
||||
# Generate hyprland.pc
|
||||
pkg_install_dir = join_paths(get_option('datadir'), 'pkgconfig')
|
||||
|
||||
import('pkgconfig').generate(
|
||||
@@ -86,5 +96,5 @@ import('pkgconfig').generate(
|
||||
url: 'https://github.com/hyprwm/Hyprland',
|
||||
description: 'Hyprland header files',
|
||||
install_dir: pkg_install_dir,
|
||||
subdirs: ['', 'hyprland/protocols', 'hyprland', 'hyprland/wlr'],
|
||||
subdirs: ['', 'hyprland/protocols', 'hyprland'],
|
||||
)
|
||||
|
@@ -1,3 +1,4 @@
|
||||
option('xwayland', type: 'feature', value: 'auto', description: 'Enable support for X11 applications')
|
||||
option('systemd', type: 'feature', value: 'auto', description: 'Enable systemd integration')
|
||||
option('legacy_renderer', type: 'feature', value: 'disabled', description: 'Enable legacy renderer')
|
||||
option('tracy_enable', type: 'boolean', value: false , description: 'Enable profiling')
|
||||
|
135
nix/default.nix
@@ -1,42 +1,36 @@
|
||||
{
|
||||
lib,
|
||||
stdenv,
|
||||
stdenvAdapters,
|
||||
pkg-config,
|
||||
pkgconf,
|
||||
makeWrapper,
|
||||
cmake,
|
||||
meson,
|
||||
ninja,
|
||||
aquamarine,
|
||||
binutils,
|
||||
cairo,
|
||||
expat,
|
||||
fribidi,
|
||||
git,
|
||||
hyprcursor,
|
||||
hyprland-protocols,
|
||||
hyprlang,
|
||||
hyprutils,
|
||||
hyprwayland-scanner,
|
||||
jq,
|
||||
libGL,
|
||||
libdatrie,
|
||||
libdrm,
|
||||
libexecinfo,
|
||||
libinput,
|
||||
libselinux,
|
||||
libsepol,
|
||||
libthai,
|
||||
libuuid,
|
||||
libxkbcommon,
|
||||
libuuid,
|
||||
mesa,
|
||||
pango,
|
||||
pciutils,
|
||||
pcre2,
|
||||
python3,
|
||||
systemd,
|
||||
tomlplusplus,
|
||||
udis86,
|
||||
udis86-hyprland,
|
||||
wayland,
|
||||
wayland-protocols,
|
||||
wayland-scanner,
|
||||
wlroots,
|
||||
xorg,
|
||||
xwayland,
|
||||
debug ? false,
|
||||
@@ -46,25 +40,39 @@
|
||||
wrapRuntimeDeps ? true,
|
||||
version ? "git",
|
||||
commit,
|
||||
revCount,
|
||||
date,
|
||||
# deprecated flags
|
||||
enableNvidiaPatches ? false,
|
||||
nvidiaPatches ? false,
|
||||
hidpiXWayland ? false,
|
||||
}:
|
||||
assert lib.assertMsg (!nvidiaPatches) "The option `nvidiaPatches` has been removed.";
|
||||
assert lib.assertMsg (!enableNvidiaPatches) "The option `enableNvidiaPatches` has been removed.";
|
||||
assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been removed. Please refer https://wiki.hyprland.org/Configuring/XWayland";
|
||||
stdenv.mkDerivation {
|
||||
pname = "hyprland${lib.optionalString debug "-debug"}";
|
||||
}: let
|
||||
inherit (builtins) baseNameOf foldl';
|
||||
inherit (lib.asserts) assertMsg;
|
||||
inherit (lib.attrsets) mapAttrsToList;
|
||||
inherit (lib.lists) flatten concatLists optional optionals;
|
||||
inherit (lib.sources) cleanSourceWith cleanSource;
|
||||
inherit (lib.strings) hasSuffix makeBinPath optionalString mesonBool mesonEnable;
|
||||
|
||||
adapters = flatten [
|
||||
stdenvAdapters.useMoldLinker
|
||||
];
|
||||
|
||||
customStdenv = foldl' (acc: adapter: adapter acc) stdenv adapters;
|
||||
in
|
||||
assert assertMsg (!nvidiaPatches) "The option `nvidiaPatches` has been removed.";
|
||||
assert assertMsg (!enableNvidiaPatches) "The option `enableNvidiaPatches` has been removed.";
|
||||
assert assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been removed. Please refer https://wiki.hyprland.org/Configuring/XWayland";
|
||||
customStdenv.mkDerivation {
|
||||
pname = "hyprland${optionalString debug "-debug"}";
|
||||
inherit version;
|
||||
|
||||
src = lib.cleanSourceWith {
|
||||
src = cleanSourceWith {
|
||||
filter = name: type: let
|
||||
baseName = baseNameOf (toString name);
|
||||
in
|
||||
! (lib.hasSuffix ".nix" baseName);
|
||||
src = lib.cleanSource ../.;
|
||||
! (hasSuffix ".nix" baseName);
|
||||
src = cleanSource ../.;
|
||||
};
|
||||
|
||||
postPatch = ''
|
||||
@@ -75,23 +83,21 @@ assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been remov
|
||||
sed -i "s#@PREFIX@/##g" hyprland.pc.in
|
||||
'';
|
||||
|
||||
COMMITS = revCount;
|
||||
DATE = date;
|
||||
DIRTY = optionalString (commit == "") "dirty";
|
||||
HASH = commit;
|
||||
DIRTY = if commit == "" then "dirty" else "";
|
||||
|
||||
nativeBuildInputs = lib.concatLists [
|
||||
[
|
||||
depsBuildBuild = [
|
||||
pkg-config
|
||||
];
|
||||
|
||||
nativeBuildInputs = [
|
||||
hyprwayland-scanner
|
||||
jq
|
||||
makeWrapper
|
||||
cmake
|
||||
meson
|
||||
ninja
|
||||
pkg-config
|
||||
python3
|
||||
wayland-scanner
|
||||
]
|
||||
# introduce this later so that cmake takes precedence
|
||||
wlroots.nativeBuildInputs
|
||||
];
|
||||
|
||||
outputs = [
|
||||
@@ -100,59 +106,66 @@ assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been remov
|
||||
"dev"
|
||||
];
|
||||
|
||||
buildInputs = lib.concatLists [
|
||||
wlroots.buildInputs
|
||||
udis86.buildInputs
|
||||
buildInputs = concatLists [
|
||||
[
|
||||
aquamarine
|
||||
cairo
|
||||
expat
|
||||
fribidi
|
||||
git
|
||||
hyprcursor.dev
|
||||
hyprcursor
|
||||
hyprland-protocols
|
||||
hyprlang
|
||||
libGL
|
||||
hyprutils
|
||||
libdrm
|
||||
libdatrie
|
||||
libGL
|
||||
libinput
|
||||
libselinux
|
||||
libsepol
|
||||
libthai
|
||||
libuuid
|
||||
libxkbcommon
|
||||
mesa
|
||||
pango
|
||||
pciutils
|
||||
pcre2
|
||||
tomlplusplus
|
||||
udis86-hyprland
|
||||
wayland
|
||||
wayland-protocols
|
||||
wayland-scanner
|
||||
xorg.libXcursor
|
||||
]
|
||||
(lib.optionals stdenv.hostPlatform.isMusl [libexecinfo])
|
||||
(lib.optionals enableXWayland [
|
||||
(optionals customStdenv.hostPlatform.isMusl [libexecinfo])
|
||||
(optionals enableXWayland [
|
||||
xorg.libxcb
|
||||
xorg.libXdmcp
|
||||
xorg.xcbutil
|
||||
xorg.xcbutilerrors
|
||||
xorg.xcbutilrenderutil
|
||||
xorg.xcbutilwm
|
||||
xwayland
|
||||
])
|
||||
(lib.optionals withSystemd [systemd])
|
||||
(optional withSystemd systemd)
|
||||
];
|
||||
|
||||
cmakeBuildType =
|
||||
mesonBuildType =
|
||||
if debug
|
||||
then "Debug"
|
||||
else "RelWithDebInfo";
|
||||
then "debugoptimized"
|
||||
else "release";
|
||||
|
||||
cmakeFlags = [
|
||||
(lib.cmakeBool "NO_XWAYLAND" (!enableXWayland))
|
||||
(lib.cmakeBool "LEGACY_RENDERER" legacyRenderer)
|
||||
(lib.cmakeBool "NO_SYSTEMD" (!withSystemd))
|
||||
# we want as much debug info as possible
|
||||
dontStrip = debug;
|
||||
|
||||
mesonFlags = flatten [
|
||||
(mapAttrsToList mesonEnable {
|
||||
"xwayland" = enableXWayland;
|
||||
"legacy_renderer" = legacyRenderer;
|
||||
"systemd" = withSystemd;
|
||||
})
|
||||
(mapAttrsToList mesonBool {
|
||||
"b_pch" = false;
|
||||
"tracy_enable" = false;
|
||||
})
|
||||
];
|
||||
|
||||
postInstall = ''
|
||||
${lib.optionalString wrapRuntimeDeps ''
|
||||
${optionalString wrapRuntimeDeps ''
|
||||
wrapProgram $out/bin/Hyprland \
|
||||
--suffix PATH : ${lib.makeBinPath [
|
||||
--suffix PATH : ${makeBinPath [
|
||||
binutils
|
||||
pciutils
|
||||
pkgconf
|
||||
@@ -162,11 +175,11 @@ assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been remov
|
||||
|
||||
passthru.providedSessions = ["hyprland"];
|
||||
|
||||
meta = with lib; {
|
||||
meta = {
|
||||
homepage = "https://github.com/hyprwm/Hyprland";
|
||||
description = "A dynamic tiling Wayland compositor that doesn't sacrifice on its looks";
|
||||
license = licenses.bsd3;
|
||||
platforms = wlroots.meta.platforms;
|
||||
description = "Dynamic tiling Wayland compositor that doesn't sacrifice on its looks";
|
||||
license = lib.licenses.bsd3;
|
||||
platforms = lib.platforms.linux;
|
||||
mainProgram = "Hyprland";
|
||||
};
|
||||
}
|
||||
|
@@ -3,13 +3,12 @@
|
||||
lib,
|
||||
inputs,
|
||||
}: let
|
||||
props = builtins.fromJSON (builtins.readFile ../props.json);
|
||||
|
||||
mkDate = longDate: (lib.concatStringsSep "-" [
|
||||
(builtins.substring 0 4 longDate)
|
||||
(builtins.substring 4 2 longDate)
|
||||
(builtins.substring 6 2 longDate)
|
||||
]);
|
||||
version = lib.removeSuffix "\n" (builtins.readFile ../VERSION);
|
||||
in {
|
||||
# Contains what a user is most likely to care about:
|
||||
# Hyprland itself, XDPH and the Share Picker.
|
||||
@@ -21,19 +20,23 @@ in {
|
||||
# Packages for variations of Hyprland, dependencies included.
|
||||
hyprland-packages = lib.composeManyExtensions [
|
||||
# Dependencies
|
||||
inputs.aquamarine.overlays.default
|
||||
inputs.hyprcursor.overlays.default
|
||||
inputs.hyprland-protocols.overlays.default
|
||||
inputs.hyprlang.overlays.default
|
||||
inputs.hyprutils.overlays.default
|
||||
inputs.hyprwayland-scanner.overlays.default
|
||||
self.overlays.xwayland
|
||||
self.overlays.udis86
|
||||
|
||||
# Hyprland packages themselves
|
||||
(final: prev: let
|
||||
date = mkDate (self.lastModifiedDate or "19700101");
|
||||
in {
|
||||
hyprland = final.callPackage ./default.nix {
|
||||
stdenv = final.gcc13Stdenv;
|
||||
version = "${props.version}+date=${date}_${self.shortRev or "dirty"}";
|
||||
stdenv = final.gcc14Stdenv;
|
||||
version = "${version}+date=${date}_${self.shortRev or "dirty"}";
|
||||
commit = self.rev or "";
|
||||
revCount = self.sourceInfo.revCount or "";
|
||||
inherit date;
|
||||
};
|
||||
hyprland-unwrapped = final.hyprland.override {wrapRuntimeDeps = false;};
|
||||
@@ -63,13 +66,19 @@ in {
|
||||
inputs.xdph.overlays.xdg-desktop-portal-hyprland
|
||||
];
|
||||
|
||||
# Patches XWayland's pkgconfig file to not include Cflags or includedir
|
||||
# The above two variables trip up CMake and the build fails
|
||||
xwayland = final: prev: {
|
||||
xwayland = prev.xwayland.overrideAttrs (old: {
|
||||
postInstall = ''
|
||||
sed -i '/includedir/d' $out/lib/pkgconfig/xwayland.pc
|
||||
'';
|
||||
# udis86 from nixpkgs is too old, and also does not provide a .pc file
|
||||
# this version is the one used in the git submodule, and allows us to
|
||||
# fetch the source without '?submodules=1'
|
||||
udis86 = final: prev: {
|
||||
udis86-hyprland = prev.udis86.overrideAttrs (self: super: {
|
||||
src = final.fetchFromGitHub {
|
||||
owner = "canihavesomecoffee";
|
||||
repo = "udis86";
|
||||
rev = "5336633af70f3917760a6d441ff02d93477b0c86";
|
||||
hash = "sha256-HifdUQPGsKQKQprByeIznvRLONdOXeolOsU5nkwIv3g=";
|
||||
};
|
||||
|
||||
patches = [];
|
||||
});
|
||||
};
|
||||
}
|
||||
|
@@ -1,17 +0,0 @@
|
||||
#!/usr/bin/env -S nix shell nixpkgs#gawk nixpkgs#git nixpkgs#gnused nixpkgs#ripgrep -c bash
|
||||
|
||||
# get wlroots revision from submodule
|
||||
SUB_REV=$(git submodule status | rg wlroots | awk '{ print substr($1,2) }')
|
||||
# and from lockfile
|
||||
CRT_REV=$(rg rev flake.nix | awk '{ print substr($3, 2, 40) }')
|
||||
|
||||
if [ "$SUB_REV" != "$CRT_REV" ]; then
|
||||
echo "Updating wlroots..."
|
||||
# update wlroots to submodule revision
|
||||
sed -Ei "s/\w{40}/$SUB_REV/g" flake.nix
|
||||
nix flake lock
|
||||
|
||||
echo "wlroots: $CRT_REV -> $SUB_REV"
|
||||
else
|
||||
echo "wlroots is up to date!"
|
||||
fi
|
@@ -1,3 +0,0 @@
|
||||
{
|
||||
"version": "0.41.0"
|
||||
}
|
@@ -1,100 +1,76 @@
|
||||
wayland_protos = dependency('wayland-protocols',
|
||||
wayland_protos = dependency(
|
||||
'wayland-protocols',
|
||||
version: '>=1.32',
|
||||
fallback: 'wayland-protocols',
|
||||
default_options: ['tests=false'],
|
||||
)
|
||||
|
||||
hyprland_protos = dependency('hyprland-protocols',
|
||||
hyprland_protos = dependency(
|
||||
'hyprland-protocols',
|
||||
version: '>=0.2',
|
||||
fallback: 'hyprland-protocols',
|
||||
)
|
||||
|
||||
wl_protocol_dir = wayland_protos.get_variable('pkgdatadir')
|
||||
hl_protocol_dir = hyprland_protos.get_variable('pkgdatadir')
|
||||
wayland_protocol_dir = wayland_protos.get_variable('pkgdatadir')
|
||||
hyprland_protocol_dir = hyprland_protos.get_variable('pkgdatadir')
|
||||
|
||||
wayland_scanner_dep = dependency('wayland-scanner', native: true)
|
||||
wayland_scanner = find_program(
|
||||
wayland_scanner_dep.get_variable('wayland_scanner'),
|
||||
native: true,
|
||||
)
|
||||
hyprwayland_scanner_dep = dependency('hyprwayland-scanner', version: '>=0.3.8', native: true)
|
||||
hyprwayland_scanner_dep = dependency('hyprwayland-scanner', version: '>=0.3.10', native: true)
|
||||
hyprwayland_scanner = find_program(
|
||||
hyprwayland_scanner_dep.get_variable('hyprwayland_scanner'),
|
||||
native: true,
|
||||
)
|
||||
|
||||
protocols = [
|
||||
[wl_protocol_dir, 'unstable/text-input/text-input-unstable-v1.xml'],
|
||||
['wlr-screencopy-unstable-v1.xml'],
|
||||
[hl_protocol_dir, 'protocols/hyprland-toplevel-export-v1.xml'],
|
||||
[hl_protocol_dir, 'protocols/hyprland-global-shortcuts-v1.xml']
|
||||
'wlr-gamma-control-unstable-v1.xml',
|
||||
'wlr-foreign-toplevel-management-unstable-v1.xml',
|
||||
'wlr-output-power-management-unstable-v1.xml',
|
||||
'input-method-unstable-v2.xml',
|
||||
'virtual-keyboard-unstable-v1.xml',
|
||||
'wlr-virtual-pointer-unstable-v1.xml',
|
||||
'wlr-output-management-unstable-v1.xml',
|
||||
'kde-server-decoration.xml',
|
||||
'wlr-layer-shell-unstable-v1.xml',
|
||||
'wayland-drm.xml',
|
||||
'wlr-data-control-unstable-v1.xml',
|
||||
'wlr-screencopy-unstable-v1.xml',
|
||||
hyprland_protocol_dir / 'protocols/hyprland-global-shortcuts-v1.xml',
|
||||
hyprland_protocol_dir / 'protocols/hyprland-toplevel-export-v1.xml',
|
||||
hyprland_protocol_dir / 'protocols/hyprland-focus-grab-v1.xml',
|
||||
wayland_protocol_dir / 'staging/tearing-control/tearing-control-v1.xml',
|
||||
wayland_protocol_dir / 'staging/fractional-scale/fractional-scale-v1.xml',
|
||||
wayland_protocol_dir / 'unstable/xdg-output/xdg-output-unstable-v1.xml',
|
||||
wayland_protocol_dir / 'staging/cursor-shape/cursor-shape-v1.xml',
|
||||
wayland_protocol_dir / 'unstable/idle-inhibit/idle-inhibit-unstable-v1.xml',
|
||||
wayland_protocol_dir / 'unstable/relative-pointer/relative-pointer-unstable-v1.xml',
|
||||
wayland_protocol_dir / 'unstable/xdg-decoration/xdg-decoration-unstable-v1.xml',
|
||||
wayland_protocol_dir / 'staging/alpha-modifier/alpha-modifier-v1.xml',
|
||||
wayland_protocol_dir / 'staging/ext-foreign-toplevel-list/ext-foreign-toplevel-list-v1.xml',
|
||||
wayland_protocol_dir / 'unstable/pointer-gestures/pointer-gestures-unstable-v1.xml',
|
||||
wayland_protocol_dir / 'unstable/keyboard-shortcuts-inhibit/keyboard-shortcuts-inhibit-unstable-v1.xml',
|
||||
wayland_protocol_dir / 'unstable/text-input/text-input-unstable-v3.xml',
|
||||
wayland_protocol_dir / 'unstable/text-input/text-input-unstable-v1.xml',
|
||||
wayland_protocol_dir / 'unstable/pointer-constraints/pointer-constraints-unstable-v1.xml',
|
||||
wayland_protocol_dir / 'staging/xdg-activation/xdg-activation-v1.xml',
|
||||
wayland_protocol_dir / 'staging/ext-idle-notify/ext-idle-notify-v1.xml',
|
||||
wayland_protocol_dir / 'staging/ext-session-lock/ext-session-lock-v1.xml',
|
||||
wayland_protocol_dir / 'stable/tablet/tablet-v2.xml',
|
||||
wayland_protocol_dir / 'stable/presentation-time/presentation-time.xml',
|
||||
wayland_protocol_dir / 'stable/xdg-shell/xdg-shell.xml',
|
||||
wayland_protocol_dir / 'unstable/primary-selection/primary-selection-unstable-v1.xml',
|
||||
wayland_protocol_dir / 'staging/xwayland-shell/xwayland-shell-v1.xml',
|
||||
wayland_protocol_dir / 'stable/viewporter/viewporter.xml',
|
||||
wayland_protocol_dir / 'stable/linux-dmabuf/linux-dmabuf-v1.xml',
|
||||
wayland_protocol_dir / 'staging/drm-lease/drm-lease-v1.xml',
|
||||
wayland_protocol_dir / 'staging/linux-drm-syncobj/linux-drm-syncobj-v1.xml',
|
||||
wayland_protocol_dir / 'staging/xdg-dialog/xdg-dialog-v1.xml',
|
||||
wayland_protocol_dir / 'staging/single-pixel-buffer/single-pixel-buffer-v1.xml',
|
||||
]
|
||||
|
||||
new_protocols = [
|
||||
['wlr-gamma-control-unstable-v1.xml'],
|
||||
['wlr-foreign-toplevel-management-unstable-v1.xml'],
|
||||
['wlr-output-power-management-unstable-v1.xml'],
|
||||
['input-method-unstable-v2.xml'],
|
||||
['virtual-keyboard-unstable-v1.xml'],
|
||||
['wlr-virtual-pointer-unstable-v1.xml'],
|
||||
['wlr-output-management-unstable-v1.xml'],
|
||||
['kde-server-decoration.xml'],
|
||||
['wlr-layer-shell-unstable-v1.xml'],
|
||||
['wayland-drm.xml'],
|
||||
['wlr-data-control-unstable-v1.xml'],
|
||||
[hl_protocol_dir, 'protocols/hyprland-focus-grab-v1.xml'],
|
||||
[wl_protocol_dir, 'staging/tearing-control/tearing-control-v1.xml'],
|
||||
[wl_protocol_dir, 'staging/fractional-scale/fractional-scale-v1.xml'],
|
||||
[wl_protocol_dir, 'unstable/xdg-output/xdg-output-unstable-v1.xml'],
|
||||
[wl_protocol_dir, 'staging/cursor-shape/cursor-shape-v1.xml'],
|
||||
[wl_protocol_dir, 'unstable/idle-inhibit/idle-inhibit-unstable-v1.xml'],
|
||||
[wl_protocol_dir, 'unstable/relative-pointer/relative-pointer-unstable-v1.xml'],
|
||||
[wl_protocol_dir, 'unstable/xdg-decoration/xdg-decoration-unstable-v1.xml'],
|
||||
[wl_protocol_dir, 'staging/alpha-modifier/alpha-modifier-v1.xml'],
|
||||
[wl_protocol_dir, 'staging/ext-foreign-toplevel-list/ext-foreign-toplevel-list-v1.xml'],
|
||||
[wl_protocol_dir, 'unstable/pointer-gestures/pointer-gestures-unstable-v1.xml'],
|
||||
[wl_protocol_dir, 'unstable/keyboard-shortcuts-inhibit/keyboard-shortcuts-inhibit-unstable-v1.xml'],
|
||||
[wl_protocol_dir, 'unstable/text-input/text-input-unstable-v3.xml'],
|
||||
[wl_protocol_dir, 'unstable/pointer-constraints/pointer-constraints-unstable-v1.xml'],
|
||||
[wl_protocol_dir, 'staging/xdg-activation/xdg-activation-v1.xml'],
|
||||
[wl_protocol_dir, 'staging/ext-idle-notify/ext-idle-notify-v1.xml'],
|
||||
[wl_protocol_dir, 'staging/ext-session-lock/ext-session-lock-v1.xml'],
|
||||
[wl_protocol_dir, 'stable/tablet/tablet-v2.xml'],
|
||||
[wl_protocol_dir, 'stable/presentation-time/presentation-time.xml'],
|
||||
[wl_protocol_dir, 'stable/xdg-shell/xdg-shell.xml'],
|
||||
[wl_protocol_dir, 'unstable/primary-selection/primary-selection-unstable-v1.xml'],
|
||||
[wl_protocol_dir, 'staging/xwayland-shell/xwayland-shell-v1.xml'],
|
||||
[wl_protocol_dir, 'stable/viewporter/viewporter.xml'],
|
||||
[wl_protocol_dir, 'stable/linux-dmabuf/linux-dmabuf-v1.xml'],
|
||||
]
|
||||
|
||||
wl_protos_src = []
|
||||
wl_protos_headers = []
|
||||
|
||||
foreach p : protocols
|
||||
xml = join_paths(p)
|
||||
wl_protos_src += custom_target(
|
||||
xml.underscorify() + '_server_c',
|
||||
input: xml,
|
||||
output: '@BASENAME@-protocol.c',
|
||||
command: [wayland_scanner, 'private-code', '@INPUT@', '@OUTPUT@'],
|
||||
)
|
||||
wl_protos_headers += custom_target(
|
||||
xml.underscorify() + '_server_h',
|
||||
input: xml,
|
||||
install: true,
|
||||
install_dir: join_paths(get_option('includedir'), 'hyprland/protocols'),
|
||||
output: '@BASENAME@-protocol.h',
|
||||
command: [wayland_scanner, 'server-header', '@INPUT@', '@OUTPUT@'],
|
||||
)
|
||||
endforeach
|
||||
|
||||
new_wl_protos = []
|
||||
foreach p : new_protocols
|
||||
xml = join_paths(p)
|
||||
new_wl_protos += custom_target(
|
||||
xml.underscorify(),
|
||||
input: xml,
|
||||
wl_protocols = []
|
||||
foreach protocol : protocols
|
||||
wl_protocols += custom_target(
|
||||
protocol.underscorify(),
|
||||
input: protocol,
|
||||
install: true,
|
||||
install_dir: [false, join_paths(get_option('includedir'), 'hyprland/protocols')],
|
||||
output: ['@BASENAME@.cpp', '@BASENAME@.hpp'],
|
||||
@@ -102,30 +78,26 @@ foreach p : new_protocols
|
||||
)
|
||||
endforeach
|
||||
|
||||
wayland_server_dep = dependency('wayland-server', version: '>=1.20.0')
|
||||
wayland_server_dir = wayland_server_dep.get_variable('pkgdatadir')
|
||||
# wayland.xml generation
|
||||
wayland_scanner = dependency('wayland-scanner')
|
||||
wayland_scanner_datadir = wayland_scanner.get_variable('pkgdatadir')
|
||||
|
||||
wl_server_protos = [
|
||||
wayland_server_dir / 'wayland.xml'
|
||||
]
|
||||
wl_server_protos_gen = []
|
||||
foreach p : wl_server_protos
|
||||
wl_server_protos_gen += custom_target(
|
||||
p.underscorify(),
|
||||
input: p,
|
||||
install: false,
|
||||
wayland_xml = wayland_scanner_datadir / 'wayland.xml'
|
||||
wayland_protocol = custom_target(
|
||||
wayland_xml.underscorify(),
|
||||
input: wayland_xml,
|
||||
install: true,
|
||||
install_dir: [false, join_paths(get_option('includedir'), 'hyprland/protocols')],
|
||||
output: ['@BASENAME@.cpp', '@BASENAME@.hpp'],
|
||||
command: [hyprwayland_scanner, '--wayland-enums', '@INPUT@', '@OUTDIR@'],
|
||||
)
|
||||
endforeach
|
||||
)
|
||||
|
||||
lib_server_protos = static_library(
|
||||
'server_protos',
|
||||
wl_protos_src + wl_protos_headers + new_wl_protos + wl_server_protos_gen,
|
||||
dependencies: wayland_server_dep.partial_dependency(compile_args: true),
|
||||
wl_protocols + wayland_protocol,
|
||||
)
|
||||
|
||||
server_protos = declare_dependency(
|
||||
link_with: lib_server_protos,
|
||||
sources: wl_protos_headers + new_wl_protos,
|
||||
sources: wl_protocols + wayland_protocol,
|
||||
)
|
||||
|
@@ -1,8 +1,8 @@
|
||||
diff --git a/CMakeLists.txt b/CMakeLists.txt
|
||||
index f54cdf5d..ad7c3e73 100755
|
||||
index f26a5c3c..3dfef333 100644
|
||||
--- a/CMakeLists.txt
|
||||
+++ b/CMakeLists.txt
|
||||
@@ -130,6 +130,8 @@ if(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG)
|
||||
@@ -143,6 +143,8 @@ if(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG)
|
||||
message(STATUS "Enabling ASan")
|
||||
|
||||
target_link_libraries(Hyprland asan)
|
||||
|
@@ -3,6 +3,7 @@
|
||||
#include <memory>
|
||||
#include <deque>
|
||||
#include <list>
|
||||
#include <sys/resource.h>
|
||||
|
||||
#include "defines.hpp"
|
||||
#include "debug/Log.hpp"
|
||||
@@ -29,6 +30,9 @@
|
||||
#include "plugins/PluginSystem.hpp"
|
||||
#include "helpers/Watchdog.hpp"
|
||||
|
||||
#include <aquamarine/backend/Backend.hpp>
|
||||
#include <aquamarine/output/Output.hpp>
|
||||
|
||||
class CWLSurfaceResource;
|
||||
|
||||
enum eManagersInitStage {
|
||||
@@ -42,22 +46,11 @@ class CCompositor {
|
||||
CCompositor();
|
||||
~CCompositor();
|
||||
|
||||
// ------------------ WLR BASICS ------------------ //
|
||||
wl_display* m_sWLDisplay;
|
||||
wl_event_loop* m_sWLEventLoop;
|
||||
wlr_backend* m_sWLRBackend;
|
||||
wlr_session* m_sWLRSession;
|
||||
wlr_renderer* m_sWLRRenderer;
|
||||
wlr_allocator* m_sWLRAllocator;
|
||||
wlr_compositor* m_sWLRCompositor;
|
||||
wlr_subcompositor* m_sWLRSubCompositor;
|
||||
wlr_drm* m_sWRLDRM;
|
||||
wlr_drm_lease_v1_manager* m_sWRLDRMLeaseMgr;
|
||||
wlr_egl* m_sWLREGL;
|
||||
int m_iDRMFD;
|
||||
wlr_linux_dmabuf_v1* m_sWLRLinuxDMABuf;
|
||||
wlr_backend* m_sWLRHeadlessBackend;
|
||||
// ------------------------------------------------- //
|
||||
int m_iDRMFD = -1;
|
||||
bool m_bInitialized = false;
|
||||
SP<Aquamarine::CBackend> m_pAqBackend;
|
||||
|
||||
std::string m_szHyprTempDataRoot = "";
|
||||
|
||||
@@ -74,13 +67,16 @@ class CCompositor {
|
||||
std::vector<PHLWINDOWREF> m_vWindowsFadingOut;
|
||||
std::vector<PHLLSREF> m_vSurfacesFadingOut;
|
||||
|
||||
std::unordered_map<std::string, uint64_t> m_mMonitorIDMap;
|
||||
std::unordered_map<std::string, MONITORID> m_mMonitorIDMap;
|
||||
|
||||
void initServer();
|
||||
void initServer(std::string socketName, int socketFd);
|
||||
void startCompositor();
|
||||
void stopCompositor();
|
||||
void cleanup();
|
||||
void createLockFile();
|
||||
void removeLockFile();
|
||||
void bumpNofile();
|
||||
void restoreNofile();
|
||||
|
||||
WP<CWLSurfaceResource> m_pLastFocus;
|
||||
PHLWINDOWREF m_pLastWindow;
|
||||
@@ -92,14 +88,16 @@ class CCompositor {
|
||||
bool m_bSessionActive = true;
|
||||
bool m_bDPMSStateON = true;
|
||||
bool m_bUnsafeState = false; // unsafe state is when there is no monitors.
|
||||
bool m_bNextIsUnsafe = false; // because wlroots
|
||||
bool m_bNextIsUnsafe = false;
|
||||
CMonitor* m_pUnsafeOutput = nullptr; // fallback output for the unsafe state
|
||||
bool m_bExitTriggered = false; // For exit dispatcher
|
||||
bool m_bIsShuttingDown = false;
|
||||
bool m_bFinalRequests = false;
|
||||
bool m_bDesktopEnvSet = false;
|
||||
bool m_bEnableXwayland = true;
|
||||
|
||||
// ------------------------------------------------- //
|
||||
|
||||
CMonitor* getMonitorFromID(const int&);
|
||||
CMonitor* getMonitorFromID(const MONITORID&);
|
||||
CMonitor* getMonitorFromName(const std::string&);
|
||||
CMonitor* getMonitorFromDesc(const std::string&);
|
||||
CMonitor* getMonitorFromCursor();
|
||||
@@ -113,60 +111,67 @@ class CCompositor {
|
||||
SP<CWLSurfaceResource> vectorToLayerPopupSurface(const Vector2D&, CMonitor* monitor, Vector2D*, PHLLS*);
|
||||
SP<CWLSurfaceResource> vectorWindowToSurface(const Vector2D&, PHLWINDOW, Vector2D& sl);
|
||||
Vector2D vectorToSurfaceLocal(const Vector2D&, PHLWINDOW, SP<CWLSurfaceResource>);
|
||||
CMonitor* getMonitorFromOutput(wlr_output*);
|
||||
CMonitor* getRealMonitorFromOutput(wlr_output*);
|
||||
CMonitor* getMonitorFromOutput(SP<Aquamarine::IOutput>);
|
||||
CMonitor* getRealMonitorFromOutput(SP<Aquamarine::IOutput>);
|
||||
PHLWINDOW getWindowFromSurface(SP<CWLSurfaceResource>);
|
||||
PHLWINDOW getWindowFromHandle(uint32_t);
|
||||
bool isWorkspaceVisible(PHLWORKSPACE);
|
||||
PHLWORKSPACE getWorkspaceByID(const int&);
|
||||
bool isWorkspaceVisibleNotCovered(PHLWORKSPACE);
|
||||
PHLWORKSPACE getWorkspaceByID(const WORKSPACEID&);
|
||||
PHLWORKSPACE getWorkspaceByName(const std::string&);
|
||||
PHLWORKSPACE getWorkspaceByString(const std::string&);
|
||||
void sanityCheckWorkspaces();
|
||||
void updateWorkspaceWindowDecos(const int&);
|
||||
void updateWorkspaceSpecialRenderData(const int&);
|
||||
int getWindowsOnWorkspace(const int& id, std::optional<bool> onlyTiled = {}, std::optional<bool> onlyVisible = {});
|
||||
int getGroupsOnWorkspace(const int& id, std::optional<bool> onlyTiled = {}, std::optional<bool> onlyVisible = {});
|
||||
void updateWorkspaceWindowDecos(const WORKSPACEID&);
|
||||
void updateWorkspaceWindowData(const WORKSPACEID&);
|
||||
int getWindowsOnWorkspace(const WORKSPACEID& id, std::optional<bool> onlyTiled = {}, std::optional<bool> onlyVisible = {});
|
||||
int getGroupsOnWorkspace(const WORKSPACEID& id, std::optional<bool> onlyTiled = {}, std::optional<bool> onlyVisible = {});
|
||||
PHLWINDOW getUrgentWindow();
|
||||
bool hasUrgentWindowOnWorkspace(const int&);
|
||||
PHLWINDOW getFirstWindowOnWorkspace(const int&);
|
||||
PHLWINDOW getTopLeftWindowOnWorkspace(const int&);
|
||||
PHLWINDOW getFullscreenWindowOnWorkspace(const int&);
|
||||
bool hasUrgentWindowOnWorkspace(const WORKSPACEID&);
|
||||
PHLWINDOW getFirstWindowOnWorkspace(const WORKSPACEID&);
|
||||
PHLWINDOW getTopLeftWindowOnWorkspace(const WORKSPACEID&);
|
||||
PHLWINDOW getFullscreenWindowOnWorkspace(const WORKSPACEID&);
|
||||
bool isWindowActive(PHLWINDOW);
|
||||
void changeWindowZOrder(PHLWINDOW, bool);
|
||||
void cleanupFadingOut(const int& monid);
|
||||
void cleanupFadingOut(const MONITORID& monid);
|
||||
PHLWINDOW getWindowInDirection(PHLWINDOW, char);
|
||||
PHLWINDOW getNextWindowOnWorkspace(PHLWINDOW, bool focusableOnly = false, std::optional<bool> floating = {});
|
||||
PHLWINDOW getPrevWindowOnWorkspace(PHLWINDOW, bool focusableOnly = false, std::optional<bool> floating = {});
|
||||
int getNextAvailableNamedWorkspace();
|
||||
WORKSPACEID getNextAvailableNamedWorkspace();
|
||||
bool isPointOnAnyMonitor(const Vector2D&);
|
||||
bool isPointOnReservedArea(const Vector2D& point, const CMonitor* monitor = nullptr);
|
||||
CMonitor* getMonitorInDirection(const char&);
|
||||
CMonitor* getMonitorInDirection(CMonitor*, const char&);
|
||||
void updateAllWindowsAnimatedDecorationValues();
|
||||
void updateWorkspaceWindows(const int64_t& id);
|
||||
void updateWorkspaceWindows(const WORKSPACEID& id);
|
||||
void updateWindowAnimatedDecorationValues(PHLWINDOW);
|
||||
int getNextAvailableMonitorID(std::string const& name);
|
||||
MONITORID getNextAvailableMonitorID(std::string const& name);
|
||||
void moveWorkspaceToMonitor(PHLWORKSPACE, CMonitor*, bool noWarpCursor = false);
|
||||
void swapActiveWorkspaces(CMonitor*, CMonitor*);
|
||||
CMonitor* getMonitorFromString(const std::string&);
|
||||
bool workspaceIDOutOfBounds(const int64_t&);
|
||||
void setWindowFullscreen(PHLWINDOW, bool, eFullscreenMode mode = FULLSCREEN_INVALID);
|
||||
bool workspaceIDOutOfBounds(const WORKSPACEID&);
|
||||
void setWindowFullscreenInternal(const PHLWINDOW PWINDOW, const eFullscreenMode MODE);
|
||||
void setWindowFullscreenClient(const PHLWINDOW PWINDOW, const eFullscreenMode MODE);
|
||||
void setWindowFullscreenState(const PHLWINDOW PWINDOW, const sFullscreenState state);
|
||||
void changeWindowFullscreenModeInternal(const PHLWINDOW PWINDOW, const eFullscreenMode MODE, const bool ON);
|
||||
void changeWindowFullscreenModeClient(const PHLWINDOW PWINDOW, const eFullscreenMode MODE, const bool ON);
|
||||
void updateFullscreenFadeOnWorkspace(PHLWORKSPACE);
|
||||
PHLWINDOW getX11Parent(PHLWINDOW);
|
||||
void scheduleFrameForMonitor(CMonitor*);
|
||||
void scheduleFrameForMonitor(CMonitor*, Aquamarine::IOutput::scheduleFrameReason reason = Aquamarine::IOutput::AQ_SCHEDULE_CLIENT_UNKNOWN);
|
||||
void addToFadingOutSafe(PHLLS);
|
||||
void removeFromFadingOutSafe(PHLLS);
|
||||
void addToFadingOutSafe(PHLWINDOW);
|
||||
PHLWINDOW getWindowByRegex(const std::string&);
|
||||
void warpCursorTo(const Vector2D&, bool force = false);
|
||||
PHLLS getLayerSurfaceFromSurface(SP<CWLSurfaceResource>);
|
||||
void closeWindow(PHLWINDOW);
|
||||
Vector2D parseWindowVectorArgsRelative(const std::string&, const Vector2D&);
|
||||
void forceReportSizesToWindowsOnWorkspace(const int&);
|
||||
PHLWORKSPACE createNewWorkspace(const int&, const int&, const std::string& name = "", bool isEmtpy = true); // will be deleted next frame if left empty and unfocused!
|
||||
void renameWorkspace(const int&, const std::string& name = "");
|
||||
void forceReportSizesToWindowsOnWorkspace(const WORKSPACEID&);
|
||||
PHLWORKSPACE createNewWorkspace(const WORKSPACEID&, const MONITORID&, const std::string& name = "",
|
||||
bool isEmpty = true); // will be deleted next frame if left empty and unfocused!
|
||||
void renameWorkspace(const WORKSPACEID&, const std::string& name = "");
|
||||
void setActiveMonitor(CMonitor*);
|
||||
bool isWorkspaceSpecial(const int&);
|
||||
int getNewSpecialID();
|
||||
bool isWorkspaceSpecial(const WORKSPACEID&);
|
||||
WORKSPACEID getNewSpecialID();
|
||||
void performUserChecks();
|
||||
void moveWindowToWorkspaceSafe(PHLWINDOW pWindow, PHLWORKSPACE pWorkspace);
|
||||
PHLWINDOW getForceFocus();
|
||||
@@ -177,6 +182,7 @@ class CCompositor {
|
||||
void setPreferredTransformForSurface(SP<CWLSurfaceResource> pSurface, wl_output_transform transform);
|
||||
void updateSuspendedStates();
|
||||
PHLWINDOW windowForCPointer(CWindow*);
|
||||
void onNewMonitor(SP<Aquamarine::IOutput> output);
|
||||
|
||||
std::string explicitConfigPath;
|
||||
|
||||
@@ -190,6 +196,7 @@ class CCompositor {
|
||||
|
||||
uint64_t m_iHyprlandPID = 0;
|
||||
wl_event_source* m_critSigSource = nullptr;
|
||||
rlimit m_sOriginalNofile = {0};
|
||||
};
|
||||
|
||||
inline std::unique_ptr<CCompositor> g_pCompositor;
|
||||
|
@@ -1,7 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include "helpers/Vector2D.hpp"
|
||||
#include "helpers/math/Math.hpp"
|
||||
#include <functional>
|
||||
#include <any>
|
||||
#include <hyprutils/math/Box.hpp>
|
||||
|
||||
using namespace Hyprutils::Math;
|
||||
|
||||
enum eIcons {
|
||||
ICON_WARNING = 0,
|
||||
@@ -37,29 +41,6 @@ struct SCallbackInfo {
|
||||
bool cancelled = false; /* on cancellable events, will cancel the event. */
|
||||
};
|
||||
|
||||
struct SWindowDecorationExtents {
|
||||
Vector2D topLeft;
|
||||
Vector2D bottomRight;
|
||||
|
||||
//
|
||||
SWindowDecorationExtents operator*(const double& scale) const {
|
||||
return SWindowDecorationExtents{topLeft * scale, bottomRight * scale};
|
||||
}
|
||||
|
||||
SWindowDecorationExtents round() {
|
||||
return {topLeft.round(), bottomRight.round()};
|
||||
}
|
||||
|
||||
bool operator==(const SWindowDecorationExtents& other) const {
|
||||
return topLeft == other.topLeft && bottomRight == other.bottomRight;
|
||||
}
|
||||
|
||||
void addExtents(const SWindowDecorationExtents& other) {
|
||||
topLeft = topLeft.getComponentMax(other.topLeft);
|
||||
bottomRight = bottomRight.getComponentMax(other.bottomRight);
|
||||
}
|
||||
};
|
||||
|
||||
enum eHyprCtlOutputFormat {
|
||||
FORMAT_NORMAL = 0,
|
||||
FORMAT_JSON
|
||||
@@ -71,4 +52,8 @@ struct SHyprCtlCommand {
|
||||
std::function<std::string(eHyprCtlOutputFormat, std::string)> fn;
|
||||
};
|
||||
|
||||
typedef int64_t WINDOWID;
|
||||
typedef int64_t MONITORID;
|
||||
typedef int64_t WORKSPACEID;
|
||||
|
||||
typedef std::function<void(void*, SCallbackInfo&, std::any)> HOOK_CALLBACK_FN;
|
||||
|
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
#include "../defines.hpp"
|
||||
#include "../helpers/VarList.hpp"
|
||||
#include "../helpers/varlist/VarList.hpp"
|
||||
#include <vector>
|
||||
|
||||
enum eConfigValueDataTypes {
|
||||
@@ -20,11 +20,11 @@ class ICustomConfigValueData {
|
||||
|
||||
class CGradientValueData : public ICustomConfigValueData {
|
||||
public:
|
||||
CGradientValueData(){};
|
||||
CGradientValueData() {};
|
||||
CGradientValueData(CColor col) {
|
||||
m_vColors.push_back(col);
|
||||
};
|
||||
virtual ~CGradientValueData(){};
|
||||
virtual ~CGradientValueData() {};
|
||||
|
||||
virtual eConfigValueDataTypes getDataType() {
|
||||
return CVD_TYPE_GRADIENT;
|
||||
@@ -67,11 +67,11 @@ class CGradientValueData : public ICustomConfigValueData {
|
||||
|
||||
class CCssGapData : public ICustomConfigValueData {
|
||||
public:
|
||||
CCssGapData() : top(0), right(0), bottom(0), left(0){};
|
||||
CCssGapData(int64_t global) : top(global), right(global), bottom(global), left(global){};
|
||||
CCssGapData(int64_t vertical, int64_t horizontal) : top(vertical), right(horizontal), bottom(vertical), left(horizontal){};
|
||||
CCssGapData(int64_t top, int64_t horizontal, int64_t bottom) : top(top), right(horizontal), bottom(bottom), left(horizontal){};
|
||||
CCssGapData(int64_t top, int64_t right, int64_t bottom, int64_t left) : top(top), right(right), bottom(bottom), left(left){};
|
||||
CCssGapData() : top(0), right(0), bottom(0), left(0) {};
|
||||
CCssGapData(int64_t global) : top(global), right(global), bottom(global), left(global) {};
|
||||
CCssGapData(int64_t vertical, int64_t horizontal) : top(vertical), right(horizontal), bottom(vertical), left(horizontal) {};
|
||||
CCssGapData(int64_t top, int64_t horizontal, int64_t bottom) : top(top), right(horizontal), bottom(bottom), left(horizontal) {};
|
||||
CCssGapData(int64_t top, int64_t right, int64_t bottom, int64_t left) : top(top), right(right), bottom(bottom), left(left) {};
|
||||
|
||||
/* Css like directions */
|
||||
int64_t top;
|
||||
|
1541
src/config/ConfigDescriptions.hpp
Normal file
@@ -6,6 +6,7 @@
|
||||
#include "../debug/Log.hpp"
|
||||
#include <unordered_map>
|
||||
#include "../defines.hpp"
|
||||
#include <variant>
|
||||
#include <vector>
|
||||
#include <deque>
|
||||
#include <algorithm>
|
||||
@@ -15,7 +16,7 @@
|
||||
#include <xf86drmMode.h>
|
||||
#include "../helpers/WLClasses.hpp"
|
||||
#include "../helpers/Monitor.hpp"
|
||||
#include "../helpers/VarList.hpp"
|
||||
#include "../helpers/varlist/VarList.hpp"
|
||||
#include "../desktop/Window.hpp"
|
||||
#include "../desktop/LayerSurface.hpp"
|
||||
|
||||
@@ -33,16 +34,16 @@ struct SWorkspaceRule {
|
||||
std::string monitor = "";
|
||||
std::string workspaceString = "";
|
||||
std::string workspaceName = "";
|
||||
int workspaceId = -1;
|
||||
WORKSPACEID workspaceId = -1;
|
||||
bool isDefault = false;
|
||||
bool isPersistent = false;
|
||||
std::optional<CCssGapData> gapsIn;
|
||||
std::optional<CCssGapData> gapsOut;
|
||||
std::optional<int64_t> borderSize;
|
||||
std::optional<int> border;
|
||||
std::optional<int> rounding;
|
||||
std::optional<int> decorate;
|
||||
std::optional<int> shadow;
|
||||
std::optional<bool> decorate;
|
||||
std::optional<bool> noRounding;
|
||||
std::optional<bool> noBorder;
|
||||
std::optional<bool> noShadow;
|
||||
std::optional<std::string> onCreatedEmptyRunCmd;
|
||||
std::optional<std::string> defaultName;
|
||||
std::map<std::string, std::string> layoutopts;
|
||||
@@ -83,6 +84,70 @@ struct SExecRequestedRule {
|
||||
uint64_t iPid = 0;
|
||||
};
|
||||
|
||||
enum eConfigOptionType : uint16_t {
|
||||
CONFIG_OPTION_BOOL = 0,
|
||||
CONFIG_OPTION_INT = 1, /* e.g. 0/1/2*/
|
||||
CONFIG_OPTION_FLOAT = 2,
|
||||
CONFIG_OPTION_STRING_SHORT = 3, /* e.g. "auto" */
|
||||
CONFIG_OPTION_STRING_LONG = 4, /* e.g. a command */
|
||||
CONFIG_OPTION_COLOR = 5,
|
||||
CONFIG_OPTION_CHOICE = 6, /* e.g. "one", "two", "three" */
|
||||
CONFIG_OPTION_GRADIENT = 7,
|
||||
CONFIG_OPTION_VECTOR = 8,
|
||||
};
|
||||
|
||||
enum eConfigOptionFlags : uint32_t {
|
||||
CONFIG_OPTION_FLAG_PERCENTAGE = (1 << 0),
|
||||
};
|
||||
|
||||
struct SConfigOptionDescription {
|
||||
|
||||
struct SBoolData {
|
||||
bool value = false;
|
||||
};
|
||||
|
||||
struct SRangeData {
|
||||
int value = 0, min = 0, max = 2;
|
||||
};
|
||||
|
||||
struct SFloatData {
|
||||
float value = 0, min = 0, max = 100;
|
||||
};
|
||||
|
||||
struct SStringData {
|
||||
std::string value;
|
||||
};
|
||||
|
||||
struct SColorData {
|
||||
CColor color;
|
||||
};
|
||||
|
||||
struct SChoiceData {
|
||||
int firstIndex = 0;
|
||||
std::string choices; // comma-separated
|
||||
};
|
||||
|
||||
struct SGradientData {
|
||||
std::string gradient;
|
||||
};
|
||||
|
||||
struct SVectorData {
|
||||
Vector2D vec, min, max;
|
||||
};
|
||||
|
||||
std::string value; // e.g. general:gaps_in
|
||||
std::string description;
|
||||
std::string specialCategory; // if value is special (e.g. device:abc) value will be abc and special device
|
||||
bool specialKey = false;
|
||||
eConfigOptionType type = CONFIG_OPTION_BOOL;
|
||||
uint32_t flags = 0; // eConfigOptionFlags
|
||||
|
||||
std::string jsonify() const;
|
||||
|
||||
//
|
||||
std::variant<SBoolData, SRangeData, SFloatData, SStringData, SColorData, SChoiceData, SGradientData, SVectorData> data;
|
||||
};
|
||||
|
||||
class CConfigManager {
|
||||
public:
|
||||
CConfigManager();
|
||||
@@ -101,11 +166,10 @@ class CConfigManager {
|
||||
void* const* getConfigValuePtr(const std::string&);
|
||||
Hyprlang::CConfigValue* getHyprlangConfigValuePtr(const std::string& name, const std::string& specialCat = "");
|
||||
void onPluginLoadUnload(const std::string& name, bool load);
|
||||
static std::string getConfigDir();
|
||||
static std::string getMainConfigPath();
|
||||
const std::string getConfigString();
|
||||
|
||||
SMonitorRule getMonitorRuleFor(const CMonitor&);
|
||||
SMonitorRule getMonitorRuleFor(const SP<CMonitor>);
|
||||
SWorkspaceRule getWorkspaceRuleFor(PHLWORKSPACE workspace);
|
||||
std::string getDefaultWorkspaceFor(const std::string&);
|
||||
|
||||
@@ -116,6 +180,8 @@ class CConfigManager {
|
||||
std::vector<SWindowRule> getMatchingRules(PHLWINDOW, bool dynamic = true, bool shadowExec = false);
|
||||
std::vector<SLayerRule> getMatchingRules(PHLLS);
|
||||
|
||||
const std::vector<SConfigOptionDescription>& getAllDescriptions();
|
||||
|
||||
std::unordered_map<std::string, SMonitorAdditionalReservedArea> m_mAdditionalReservedAreas;
|
||||
|
||||
std::unordered_map<std::string, SAnimationPropertyConfig> getAnimationConfig();
|
||||
@@ -126,13 +192,11 @@ class CConfigManager {
|
||||
|
||||
// no-op when done.
|
||||
void dispatchExecOnce();
|
||||
void dispatchExecShutdown();
|
||||
|
||||
void performMonitorReload();
|
||||
void appendMonitorRule(const SMonitorRule&);
|
||||
bool replaceMonitorRule(const SMonitorRule&);
|
||||
bool m_bWantsMonitorReload = false;
|
||||
bool m_bForceReload = false;
|
||||
bool m_bNoMonitorReload = false;
|
||||
void ensureMonitorStatus();
|
||||
void ensureVRR(CMonitor* pMonitor = nullptr);
|
||||
|
||||
@@ -150,6 +214,7 @@ class CConfigManager {
|
||||
// keywords
|
||||
std::optional<std::string> handleRawExec(const std::string&, const std::string&);
|
||||
std::optional<std::string> handleExecOnce(const std::string&, const std::string&);
|
||||
std::optional<std::string> handleExecShutdown(const std::string&, const std::string&);
|
||||
std::optional<std::string> handleMonitor(const std::string&, const std::string&);
|
||||
std::optional<std::string> handleBind(const std::string&, const std::string&);
|
||||
std::optional<std::string> handleUnbind(const std::string&, const std::string&);
|
||||
@@ -168,6 +233,37 @@ class CConfigManager {
|
||||
|
||||
std::string configCurrentPath;
|
||||
|
||||
std::unordered_map<std::string, std::function<CWindowOverridableVar<bool>*(PHLWINDOW)>> mbWindowProperties = {
|
||||
{"allowsinput", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.allowsInput; }},
|
||||
{"dimaround", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.dimAround; }},
|
||||
{"decorate", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.decorate; }},
|
||||
{"focusonactivate", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.focusOnActivate; }},
|
||||
{"keepaspectratio", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.keepAspectRatio; }},
|
||||
{"nearestneighbor", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.nearestNeighbor; }},
|
||||
{"noanim", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.noAnim; }},
|
||||
{"noblur", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.noBlur; }},
|
||||
{"noborder", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.noBorder; }},
|
||||
{"nodim", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.noDim; }},
|
||||
{"nofocus", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.noFocus; }},
|
||||
{"nomaxsize", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.noMaxSize; }},
|
||||
{"norounding", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.noRounding; }},
|
||||
{"noshadow", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.noShadow; }},
|
||||
{"noshortcutsinhibit", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.noShortcutsInhibit; }},
|
||||
{"opaque", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.opaque; }},
|
||||
{"forcergbx", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.RGBX; }},
|
||||
{"syncfullscreen", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.syncFullscreen; }},
|
||||
{"immediate", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.tearing; }},
|
||||
{"xray", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.xray; }},
|
||||
};
|
||||
|
||||
std::unordered_map<std::string, std::function<CWindowOverridableVar<int>*(PHLWINDOW)>> miWindowProperties = {
|
||||
{"rounding", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.rounding; }}, {"bordersize", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.borderSize; }}};
|
||||
|
||||
bool m_bWantsMonitorReload = false;
|
||||
bool m_bForceReload = false;
|
||||
bool m_bNoMonitorReload = false;
|
||||
bool isLaunchingExecOnce = false; // For exec-once to skip initial ws tracking
|
||||
|
||||
private:
|
||||
std::unique_ptr<Hyprlang::CConfig> m_pConfig;
|
||||
|
||||
@@ -195,6 +291,7 @@ class CConfigManager {
|
||||
bool firstExecDispatched = false;
|
||||
bool m_bManualCrashInitiated = false;
|
||||
std::deque<std::string> firstExecRequests;
|
||||
std::deque<std::string> finalExecRequests;
|
||||
|
||||
std::vector<std::pair<std::string, std::string>> m_vFailedPluginConfigValues; // for plugin values of unloaded plugins
|
||||
std::string m_szConfigErrors = "";
|
||||
@@ -204,7 +301,8 @@ class CConfigManager {
|
||||
void updateBlurredLS(const std::string&, const bool);
|
||||
void setDefaultAnimationVars();
|
||||
std::optional<std::string> resetHLConfig();
|
||||
std::optional<std::string> verifyConfigExists();
|
||||
static std::optional<std::string> generateConfig(std::string configPath);
|
||||
static std::optional<std::string> verifyConfigExists();
|
||||
void postConfigReload(const Hyprlang::CParseResult& result);
|
||||
void reload();
|
||||
SWorkspaceRule mergeWorkspaceRules(const SWorkspaceRule&, const SWorkspaceRule&);
|
||||
|
@@ -11,7 +11,7 @@ template <typename T>
|
||||
class CConfigValue {
|
||||
public:
|
||||
CConfigValue(const std::string& val) {
|
||||
const auto PVHYPRLANG = g_pConfigManager->getHyprlangConfigValuePtr(val.c_str());
|
||||
const auto PVHYPRLANG = g_pConfigManager->getHyprlangConfigValuePtr(val);
|
||||
|
||||
p_ = PVHYPRLANG->getDataStaticPtr();
|
||||
|
||||
|
@@ -138,7 +138,7 @@ dwindle {
|
||||
|
||||
# See https://wiki.hyprland.org/Configuring/Master-Layout/ for more
|
||||
master {
|
||||
new_is_master = true
|
||||
new_status = master
|
||||
}
|
||||
|
||||
# https://wiki.hyprland.org/Configuring/Variables/#misc
|
||||
@@ -182,9 +182,9 @@ device {
|
||||
}
|
||||
|
||||
|
||||
####################
|
||||
### KEYBINDINGSS ###
|
||||
####################
|
||||
###################
|
||||
### KEYBINDINGS ###
|
||||
###################
|
||||
|
||||
# See https://wiki.hyprland.org/Configuring/Keywords/
|
||||
$mainMod = SUPER # Sets "Windows" key as main modifier
|
||||
@@ -241,6 +241,19 @@ bind = $mainMod, mouse_up, workspace, e-1
|
||||
bindm = $mainMod, mouse:272, movewindow
|
||||
bindm = $mainMod, mouse:273, resizewindow
|
||||
|
||||
# Laptop multimedia keys for volume and LCD brightness
|
||||
bindel = ,XF86AudioRaiseVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%+
|
||||
bindel = ,XF86AudioLowerVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%-
|
||||
bindel = ,XF86AudioMute, exec, wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle
|
||||
bindel = ,XF86AudioMicMute, exec, wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle
|
||||
bindel = ,XF86MonBrightnessUp, exec, brightnessctl s 10%+
|
||||
bindel = ,XF86MonBrightnessDown, exec, brightnessctl s 10%-
|
||||
|
||||
# Requires playerctl
|
||||
bindl = , XF86AudioNext, exec, playerctl next
|
||||
bindl = , XF86AudioPause, exec, playerctl play-pause
|
||||
bindl = , XF86AudioPlay, exec, playerctl play-pause
|
||||
bindl = , XF86AudioPrev, exec, playerctl previous
|
||||
|
||||
##############################
|
||||
### WINDOWS AND WORKSPACES ###
|
||||
@@ -255,5 +268,9 @@ bindm = $mainMod, mouse:273, resizewindow
|
||||
# Example windowrule v2
|
||||
# windowrulev2 = float,class:^(kitty)$,title:^(kitty)$
|
||||
|
||||
windowrulev2 = suppressevent maximize, class:.* # You'll probably like this.
|
||||
# Ignore maximize requests from apps. You'll probably like this.
|
||||
windowrulev2 = suppressevent maximize, class:.*
|
||||
|
||||
# Fix some dragging issues with XWayland
|
||||
windowrulev2 = nofocus,class:^$,title:^$,xwayland:1,floating:1,fullscreen:0,pinned:0
|
||||
)#";
|
||||
|
@@ -5,6 +5,7 @@
|
||||
#include <time.h>
|
||||
#include <errno.h>
|
||||
#include <sys/stat.h>
|
||||
#include <filesystem>
|
||||
|
||||
#include "../plugins/PluginSystem.hpp"
|
||||
#include "../signal-safe.hpp"
|
||||
@@ -85,7 +86,7 @@ void CrashReporter::createAndSaveCrash(int sig) {
|
||||
stderr.flush();
|
||||
}
|
||||
|
||||
reportFd = open(reportPath.get_str(), O_WRONLY | O_CREAT, S_IRWXU);
|
||||
reportFd = open(reportPath.get_str(), O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
|
||||
if (reportFd < 0) {
|
||||
exit_with_error("Failed to open crash report path for writing");
|
||||
}
|
||||
@@ -104,7 +105,19 @@ void CrashReporter::createAndSaveCrash(int sig) {
|
||||
finalCrashReport += GIT_COMMIT_HASH;
|
||||
finalCrashReport += "\nTag: ";
|
||||
finalCrashReport += GIT_TAG;
|
||||
finalCrashReport += "\n\n";
|
||||
finalCrashReport += "\nDate: ";
|
||||
finalCrashReport += GIT_COMMIT_DATE;
|
||||
finalCrashReport += "\nFlags:\n";
|
||||
#ifdef LEGACY_RENDERER
|
||||
finalCrashReport += "legacyrenderer\n";
|
||||
#endif
|
||||
#ifndef ISDEBUG
|
||||
finalCrashReport += "debug\n";
|
||||
#endif
|
||||
#ifdef NO_XWAYLAND
|
||||
finalCrashReport += "no xwayland\n";
|
||||
#endif
|
||||
finalCrashReport += "\n";
|
||||
|
||||
if (g_pPluginSystem && g_pPluginSystem->pluginCount() > 0) {
|
||||
finalCrashReport += "Hyprland seems to be running with plugins. This crash might not be Hyprland's fault.\nPlugins:\n";
|
||||
|
@@ -5,6 +5,9 @@
|
||||
#include "../helpers/MiscFunctions.hpp"
|
||||
#include <functional>
|
||||
|
||||
// exposed for main.cpp
|
||||
std::string systemInfoRequest(eHyprCtlOutputFormat format, std::string request);
|
||||
|
||||
class CHyprCtl {
|
||||
public:
|
||||
CHyprCtl();
|
||||
@@ -22,11 +25,16 @@ class CHyprCtl {
|
||||
bool sysInfoConfig = false;
|
||||
} m_sCurrentRequestParams;
|
||||
|
||||
static std::string getWindowData(PHLWINDOW w, eHyprCtlOutputFormat format);
|
||||
static std::string getWorkspaceData(PHLWORKSPACE w, eHyprCtlOutputFormat format);
|
||||
static std::string getMonitorData(Hyprutils::Memory::CSharedPointer<CMonitor> m, eHyprCtlOutputFormat format);
|
||||
|
||||
private:
|
||||
void startHyprCtlSocket();
|
||||
|
||||
std::vector<SP<SHyprCtlCommand>> m_vCommands;
|
||||
wl_event_source* m_eventSource = nullptr;
|
||||
std::string m_socketPath;
|
||||
};
|
||||
|
||||
inline std::unique_ptr<CHyprCtl> g_pHyprCtl;
|
||||
|
@@ -7,8 +7,8 @@ CHyprDebugOverlay::CHyprDebugOverlay() {
|
||||
m_pTexture = makeShared<CTexture>();
|
||||
}
|
||||
|
||||
void CHyprMonitorDebugOverlay::renderData(CMonitor* pMonitor, float µs) {
|
||||
m_dLastRenderTimes.push_back(µs / 1000.f);
|
||||
void CHyprMonitorDebugOverlay::renderData(CMonitor* pMonitor, float durationUs) {
|
||||
m_dLastRenderTimes.push_back(durationUs / 1000.f);
|
||||
|
||||
if (m_dLastRenderTimes.size() > (long unsigned int)pMonitor->refreshRate)
|
||||
m_dLastRenderTimes.pop_front();
|
||||
@@ -17,8 +17,8 @@ void CHyprMonitorDebugOverlay::renderData(CMonitor* pMonitor, float µs) {
|
||||
m_pMonitor = pMonitor;
|
||||
}
|
||||
|
||||
void CHyprMonitorDebugOverlay::renderDataNoOverlay(CMonitor* pMonitor, float µs) {
|
||||
m_dLastRenderTimesNoOverlay.push_back(µs / 1000.f);
|
||||
void CHyprMonitorDebugOverlay::renderDataNoOverlay(CMonitor* pMonitor, float durationUs) {
|
||||
m_dLastRenderTimesNoOverlay.push_back(durationUs / 1000.f);
|
||||
|
||||
if (m_dLastRenderTimesNoOverlay.size() > (long unsigned int)pMonitor->refreshRate)
|
||||
m_dLastRenderTimesNoOverlay.pop_front();
|
||||
@@ -57,7 +57,7 @@ int CHyprMonitorDebugOverlay::draw(int offset) {
|
||||
float avgFrametime = 0;
|
||||
float maxFrametime = 0;
|
||||
float minFrametime = 9999;
|
||||
for (auto& ft : m_dLastFrametimes) {
|
||||
for (auto const& ft : m_dLastFrametimes) {
|
||||
if (ft > maxFrametime)
|
||||
maxFrametime = ft;
|
||||
if (ft < minFrametime)
|
||||
@@ -70,7 +70,7 @@ int CHyprMonitorDebugOverlay::draw(int offset) {
|
||||
float avgRenderTime = 0;
|
||||
float maxRenderTime = 0;
|
||||
float minRenderTime = 9999;
|
||||
for (auto& rt : m_dLastRenderTimes) {
|
||||
for (auto const& rt : m_dLastRenderTimes) {
|
||||
if (rt > maxRenderTime)
|
||||
maxRenderTime = rt;
|
||||
if (rt < minRenderTime)
|
||||
@@ -83,7 +83,7 @@ int CHyprMonitorDebugOverlay::draw(int offset) {
|
||||
float avgRenderTimeNoOverlay = 0;
|
||||
float maxRenderTimeNoOverlay = 0;
|
||||
float minRenderTimeNoOverlay = 9999;
|
||||
for (auto& rt : m_dLastRenderTimesNoOverlay) {
|
||||
for (auto const& rt : m_dLastRenderTimesNoOverlay) {
|
||||
if (rt > maxRenderTimeNoOverlay)
|
||||
maxRenderTimeNoOverlay = rt;
|
||||
if (rt < minRenderTimeNoOverlay)
|
||||
@@ -96,7 +96,7 @@ int CHyprMonitorDebugOverlay::draw(int offset) {
|
||||
float avgAnimMgrTick = 0;
|
||||
float maxAnimMgrTick = 0;
|
||||
float minAnimMgrTick = 9999;
|
||||
for (auto& at : m_dLastAnimationTicks) {
|
||||
for (auto const& at : m_dLastAnimationTicks) {
|
||||
if (at > maxAnimMgrTick)
|
||||
maxAnimMgrTick = at;
|
||||
if (at < minAnimMgrTick)
|
||||
@@ -188,12 +188,12 @@ int CHyprMonitorDebugOverlay::draw(int offset) {
|
||||
return posY - offset;
|
||||
}
|
||||
|
||||
void CHyprDebugOverlay::renderData(CMonitor* pMonitor, float µs) {
|
||||
m_mMonitorOverlays[pMonitor].renderData(pMonitor, µs);
|
||||
void CHyprDebugOverlay::renderData(CMonitor* pMonitor, float durationUs) {
|
||||
m_mMonitorOverlays[pMonitor].renderData(pMonitor, durationUs);
|
||||
}
|
||||
|
||||
void CHyprDebugOverlay::renderDataNoOverlay(CMonitor* pMonitor, float µs) {
|
||||
m_mMonitorOverlays[pMonitor].renderDataNoOverlay(pMonitor, µs);
|
||||
void CHyprDebugOverlay::renderDataNoOverlay(CMonitor* pMonitor, float durationUs) {
|
||||
m_mMonitorOverlays[pMonitor].renderDataNoOverlay(pMonitor, durationUs);
|
||||
}
|
||||
|
||||
void CHyprDebugOverlay::frameData(CMonitor* pMonitor) {
|
||||
@@ -217,7 +217,7 @@ void CHyprDebugOverlay::draw() {
|
||||
|
||||
// draw the things
|
||||
int offsetY = 0;
|
||||
for (auto& m : g_pCompositor->m_vMonitors) {
|
||||
for (auto const& m : g_pCompositor->m_vMonitors) {
|
||||
offsetY += m_mMonitorOverlays[m.get()].draw(offsetY);
|
||||
offsetY += 5; // for padding between mons
|
||||
}
|
||||
|
@@ -13,8 +13,8 @@ class CHyprMonitorDebugOverlay {
|
||||
public:
|
||||
int draw(int offset);
|
||||
|
||||
void renderData(CMonitor* pMonitor, float µs);
|
||||
void renderDataNoOverlay(CMonitor* pMonitor, float µs);
|
||||
void renderData(CMonitor* pMonitor, float durationUs);
|
||||
void renderDataNoOverlay(CMonitor* pMonitor, float durationUs);
|
||||
void frameData(CMonitor* pMonitor);
|
||||
|
||||
private:
|
||||
@@ -33,8 +33,8 @@ class CHyprDebugOverlay {
|
||||
public:
|
||||
CHyprDebugOverlay();
|
||||
void draw();
|
||||
void renderData(CMonitor*, float µs);
|
||||
void renderDataNoOverlay(CMonitor*, float µs);
|
||||
void renderData(CMonitor*, float durationUs);
|
||||
void renderDataNoOverlay(CMonitor*, float durationUs);
|
||||
void frameData(CMonitor*);
|
||||
|
||||
private:
|
||||
|
@@ -44,7 +44,7 @@ void CHyprNotificationOverlay::addNotification(const std::string& text, const CC
|
||||
PNOTIF->icon = icon;
|
||||
PNOTIF->fontSize = fontSize;
|
||||
|
||||
for (auto& m : g_pCompositor->m_vMonitors) {
|
||||
for (auto const& m : g_pCompositor->m_vMonitors) {
|
||||
g_pCompositor->scheduleFrameForMonitor(m.get());
|
||||
}
|
||||
}
|
||||
@@ -87,7 +87,7 @@ CBox CHyprNotificationOverlay::drawNotifications(CMonitor* pMonitor) {
|
||||
const auto iconBackendID = iconBackendFromLayout(layout);
|
||||
const auto PBEZIER = g_pAnimationManager->getBezier("default");
|
||||
|
||||
for (auto& notif : m_dNotifications) {
|
||||
for (auto const& notif : m_dNotifications) {
|
||||
const auto ICONPADFORNOTIF = notif->icon == ICON_NONE ? 0 : ICON_PAD;
|
||||
const auto FONTSIZE = std::clamp((int)(notif->fontSize * ((pMonitor->vecPixelSize.x * SCALE) / 1920.f)), 8, 40);
|
||||
|
||||
@@ -131,7 +131,7 @@ CBox CHyprNotificationOverlay::drawNotifications(CMonitor* pMonitor) {
|
||||
textW /= PANGO_SCALE;
|
||||
textH /= PANGO_SCALE;
|
||||
|
||||
const auto NOTIFSIZE = Vector2D{textW + 20 + iconW + 2 * ICONPADFORNOTIF, textH + 10};
|
||||
const auto NOTIFSIZE = Vector2D{textW + 20.0 + iconW + 2 * ICONPADFORNOTIF, textH + 10.0};
|
||||
|
||||
// draw rects
|
||||
cairo_set_source_rgba(m_pCairo, notif->color.r, notif->color.g, notif->color.b, notif->color.a);
|
||||
|
@@ -1,36 +1,21 @@
|
||||
#include "Log.hpp"
|
||||
#include "../defines.hpp"
|
||||
#include "../Compositor.hpp"
|
||||
#include "RollingLogFollow.hpp"
|
||||
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <fcntl.h>
|
||||
|
||||
void Debug::init(const std::string& IS) {
|
||||
logFile = IS + (ISDEBUG ? "/hyprlandd.log" : "/hyprland.log");
|
||||
logOfs.open(logFile, std::ios::out | std::ios::app);
|
||||
auto handle = logOfs.native_handle();
|
||||
fcntl(handle, F_SETFD, FD_CLOEXEC);
|
||||
}
|
||||
|
||||
void Debug::wlrLog(wlr_log_importance level, const char* fmt, va_list args) {
|
||||
if (level > wlr_log_get_verbosity())
|
||||
return;
|
||||
|
||||
char* outputStr = nullptr;
|
||||
|
||||
vasprintf(&outputStr, fmt, args);
|
||||
|
||||
std::string output = std::string(outputStr);
|
||||
free(outputStr);
|
||||
|
||||
rollingLog += output + "\n";
|
||||
|
||||
if (!disableLogs || !**disableLogs) {
|
||||
std::ofstream ofs;
|
||||
ofs.open(logFile, std::ios::out | std::ios::app);
|
||||
ofs << "[wlr] " << output << "\n";
|
||||
ofs.close();
|
||||
}
|
||||
|
||||
if (!disableStdout)
|
||||
std::cout << output << "\n";
|
||||
void Debug::close() {
|
||||
logOfs.close();
|
||||
}
|
||||
|
||||
void Debug::log(LogLevel level, std::string str) {
|
||||
@@ -73,13 +58,13 @@ void Debug::log(LogLevel level, std::string str) {
|
||||
if (rollingLog.size() > ROLLING_LOG_SIZE)
|
||||
rollingLog = rollingLog.substr(rollingLog.size() - ROLLING_LOG_SIZE);
|
||||
|
||||
if (RollingLogFollow::Get().IsRunning())
|
||||
RollingLogFollow::Get().AddLog(str);
|
||||
|
||||
if (!disableLogs || !**disableLogs) {
|
||||
// log to a file
|
||||
std::ofstream ofs;
|
||||
ofs.open(logFile, std::ios::out | std::ios::app);
|
||||
ofs << str << "\n";
|
||||
|
||||
ofs.close();
|
||||
logOfs << str << "\n";
|
||||
logOfs.flush();
|
||||
}
|
||||
|
||||
// log it to the stdout too.
|
||||
|
@@ -4,6 +4,7 @@
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <chrono>
|
||||
#include <mutex>
|
||||
#include "../includes.hpp"
|
||||
#include "../helpers/MiscFunctions.hpp"
|
||||
|
||||
@@ -22,6 +23,7 @@ enum LogLevel {
|
||||
|
||||
namespace Debug {
|
||||
inline std::string logFile;
|
||||
inline std::ofstream logOfs;
|
||||
inline int64_t* const* disableLogs = nullptr;
|
||||
inline int64_t* const* disableTime = nullptr;
|
||||
inline bool disableStdout = false;
|
||||
@@ -30,14 +32,18 @@ namespace Debug {
|
||||
inline int64_t* const* coloredLogs = nullptr;
|
||||
|
||||
inline std::string rollingLog = ""; // rolling log contains the ROLLING_LOG_SIZE tail of the log
|
||||
inline std::mutex logMutex;
|
||||
|
||||
void init(const std::string& IS);
|
||||
void close();
|
||||
|
||||
//
|
||||
void log(LogLevel level, std::string str);
|
||||
|
||||
template <typename... Args>
|
||||
void log(LogLevel level, std::format_string<Args...> fmt, Args&&... args) {
|
||||
std::lock_guard<std::mutex> guard(logMutex);
|
||||
|
||||
if (level == TRACE && !trace)
|
||||
return;
|
||||
|
||||
@@ -49,7 +55,8 @@ namespace Debug {
|
||||
// print date and time to the ofs
|
||||
if (disableTime && !**disableTime) {
|
||||
#ifndef _LIBCPP_VERSION
|
||||
const auto zt = std::chrono::zoned_time{std::chrono::current_zone(), std::chrono::system_clock::now()};
|
||||
static auto current_zone = std::chrono::current_zone();
|
||||
const auto zt = std::chrono::zoned_time{current_zone, std::chrono::system_clock::now()};
|
||||
const auto hms = std::chrono::hh_mm_ss{zt.get_local_time() - std::chrono::floor<std::chrono::days>(zt.get_local_time())};
|
||||
#else
|
||||
// TODO: current clang 17 does not support `zoned_time`, remove this once clang 19 is ready
|
||||
@@ -67,6 +74,4 @@ namespace Debug {
|
||||
|
||||
log(level, logMsg);
|
||||
}
|
||||
|
||||
void wlrLog(wlr_log_importance level, const char* fmt, va_list args);
|
||||
};
|
||||
|
65
src/debug/RollingLogFollow.hpp
Normal file
@@ -0,0 +1,65 @@
|
||||
#pragma once
|
||||
|
||||
#include <shared_mutex>
|
||||
|
||||
namespace Debug {
|
||||
struct RollingLogFollow {
|
||||
std::unordered_map<int, std::string> socketToRollingLogFollowQueue;
|
||||
std::shared_mutex m;
|
||||
bool running = false;
|
||||
static constexpr size_t ROLLING_LOG_FOLLOW_TOO_BIG = 8192;
|
||||
|
||||
// Returns true if the queue is empty for the given socket
|
||||
bool isEmpty(int socket) {
|
||||
std::shared_lock<std::shared_mutex> r(m);
|
||||
return socketToRollingLogFollowQueue[socket].empty();
|
||||
}
|
||||
|
||||
std::string DebugInfo() {
|
||||
std::shared_lock<std::shared_mutex> r(m);
|
||||
return std::format("RollingLogFollow, got {} connections", socketToRollingLogFollowQueue.size());
|
||||
}
|
||||
|
||||
std::string GetLog(int socket) {
|
||||
std::unique_lock<std::shared_mutex> w(m);
|
||||
|
||||
const std::string ret = socketToRollingLogFollowQueue[socket];
|
||||
socketToRollingLogFollowQueue[socket] = "";
|
||||
|
||||
return ret;
|
||||
};
|
||||
|
||||
void AddLog(std::string log) {
|
||||
std::unique_lock<std::shared_mutex> w(m);
|
||||
running = true;
|
||||
std::vector<int> to_erase;
|
||||
for (const auto& p : socketToRollingLogFollowQueue)
|
||||
socketToRollingLogFollowQueue[p.first] += log + "\n";
|
||||
}
|
||||
|
||||
bool IsRunning() {
|
||||
std::shared_lock<std::shared_mutex> r(m);
|
||||
return running;
|
||||
}
|
||||
|
||||
void StopFor(int socket) {
|
||||
std::unique_lock<std::shared_mutex> w(m);
|
||||
socketToRollingLogFollowQueue.erase(socket);
|
||||
if (socketToRollingLogFollowQueue.empty())
|
||||
running = false;
|
||||
}
|
||||
|
||||
void StartFor(int socket) {
|
||||
std::unique_lock<std::shared_mutex> w(m);
|
||||
socketToRollingLogFollowQueue[socket] = std::format("[LOG] Following log to socket: {} started\n", socket);
|
||||
running = true;
|
||||
}
|
||||
|
||||
static RollingLogFollow& Get() {
|
||||
static RollingLogFollow instance;
|
||||
static std::mutex gm;
|
||||
std::lock_guard<std::mutex> lock(gm);
|
||||
return instance;
|
||||
};
|
||||
};
|
||||
}
|
@@ -1,6 +1,5 @@
|
||||
#include "includes.hpp"
|
||||
#include "debug/Log.hpp"
|
||||
#include "helpers/WLListener.hpp"
|
||||
#include "helpers/Color.hpp"
|
||||
#include "macros.hpp"
|
||||
#include "desktop/DesktopTypes.hpp"
|
||||
|
@@ -71,10 +71,16 @@ CLayerSurface::~CLayerSurface() {
|
||||
surface->unassign();
|
||||
g_pHyprRenderer->makeEGLCurrent();
|
||||
std::erase_if(g_pHyprOpenGL->m_mLayerFramebuffers, [&](const auto& other) { return other.first.expired() || other.first.lock() == self.lock(); });
|
||||
|
||||
for (auto const& mon : g_pCompositor->m_vRealMonitors) {
|
||||
for (auto& lsl : mon->m_aLayerSurfaceLayers) {
|
||||
std::erase_if(lsl, [this](auto& ls) { return ls.expired() || ls.get() == this; });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CLayerSurface::onDestroy() {
|
||||
Debug::log(LOG, "LayerSurface {:x} destroyed", (uintptr_t)layerSurface);
|
||||
Debug::log(LOG, "LayerSurface {:x} destroyed", (uintptr_t)layerSurface.get());
|
||||
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(monitorID);
|
||||
|
||||
@@ -111,13 +117,24 @@ void CLayerSurface::onDestroy() {
|
||||
layerSurface.reset();
|
||||
if (surface)
|
||||
surface->unassign();
|
||||
|
||||
listeners.unmap.reset();
|
||||
listeners.destroy.reset();
|
||||
listeners.map.reset();
|
||||
listeners.commit.reset();
|
||||
}
|
||||
|
||||
void CLayerSurface::onMap() {
|
||||
Debug::log(LOG, "LayerSurface {:x} mapped", (uintptr_t)layerSurface);
|
||||
Debug::log(LOG, "LayerSurface {:x} mapped", (uintptr_t)layerSurface.get());
|
||||
|
||||
mapped = true;
|
||||
keyboardExclusive = layerSurface->current.interactivity;
|
||||
interactivity = layerSurface->current.interactivity;
|
||||
|
||||
layerSurface->surface->map();
|
||||
|
||||
// this layer might be re-mapped.
|
||||
fadingOut = false;
|
||||
g_pCompositor->removeFromFadingOutSafe(self.lock());
|
||||
|
||||
// fix if it changed its mon
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(monitorID);
|
||||
@@ -133,12 +150,15 @@ void CLayerSurface::onMap() {
|
||||
|
||||
surface->resource()->enter(PMONITOR->self.lock());
|
||||
|
||||
if (layerSurface->current.interactivity == ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_EXCLUSIVE)
|
||||
const bool ISEXCLUSIVE = layerSurface->current.interactivity == ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_EXCLUSIVE;
|
||||
|
||||
if (ISEXCLUSIVE)
|
||||
g_pInputManager->m_dExclusiveLSes.push_back(self);
|
||||
|
||||
const bool GRABSFOCUS = layerSurface->current.interactivity != ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_NONE &&
|
||||
const bool GRABSFOCUS = ISEXCLUSIVE ||
|
||||
(layerSurface->current.interactivity != ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_NONE &&
|
||||
// don't focus if constrained
|
||||
(g_pSeatManager->mouse.expired() || !g_pInputManager->isConstrained());
|
||||
(g_pSeatManager->mouse.expired() || !g_pInputManager->isConstrained()));
|
||||
|
||||
if (GRABSFOCUS) {
|
||||
// TODO: use the new superb really very cool grab
|
||||
@@ -156,7 +176,7 @@ void CLayerSurface::onMap() {
|
||||
CBox geomFixed = {geometry.x + PMONITOR->vecPosition.x, geometry.y + PMONITOR->vecPosition.y, geometry.width, geometry.height};
|
||||
g_pHyprRenderer->damageBox(&geomFixed);
|
||||
const auto WORKSPACE = PMONITOR->activeWorkspace;
|
||||
const bool FULLSCREEN = WORKSPACE->m_bHasFullscreenWindow && WORKSPACE->m_efFullscreenMode == FULLSCREEN_FULL;
|
||||
const bool FULLSCREEN = WORKSPACE->m_bHasFullscreenWindow && WORKSPACE->m_efFullscreenMode == FSMODE_FULLSCREEN;
|
||||
|
||||
startAnimation(!(layer == ZWLR_LAYER_SHELL_V1_LAYER_TOP && FULLSCREEN && !GRABSFOCUS));
|
||||
readyToDelete = false;
|
||||
@@ -170,22 +190,21 @@ void CLayerSurface::onMap() {
|
||||
}
|
||||
|
||||
void CLayerSurface::onUnmap() {
|
||||
Debug::log(LOG, "LayerSurface {:x} unmapped", (uintptr_t)layerSurface);
|
||||
Debug::log(LOG, "LayerSurface {:x} unmapped", (uintptr_t)layerSurface.get());
|
||||
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"closelayer", layerSurface->layerNamespace});
|
||||
EMIT_HOOK_EVENT("closeLayer", self.lock());
|
||||
|
||||
std::erase_if(g_pInputManager->m_dExclusiveLSes, [this](const auto& other) { return !other.lock() || other.lock() == self.lock(); });
|
||||
|
||||
if (!g_pInputManager->m_dExclusiveLSes.empty())
|
||||
g_pCompositor->focusSurface(g_pInputManager->m_dExclusiveLSes[0]->surface->resource());
|
||||
|
||||
if (!g_pCompositor->getMonitorFromID(monitorID) || g_pCompositor->m_bUnsafeState) {
|
||||
Debug::log(WARN, "Layersurface unmapping on invalid monitor (removed?) ignoring.");
|
||||
|
||||
g_pCompositor->addToFadingOutSafe(self.lock());
|
||||
|
||||
mapped = false;
|
||||
if (layerSurface && layerSurface->surface)
|
||||
layerSurface->surface->unmap();
|
||||
|
||||
startAnimation(false);
|
||||
return;
|
||||
@@ -197,6 +216,8 @@ void CLayerSurface::onUnmap() {
|
||||
startAnimation(false);
|
||||
|
||||
mapped = false;
|
||||
if (layerSurface && layerSurface->surface)
|
||||
layerSurface->surface->unmap();
|
||||
|
||||
g_pCompositor->addToFadingOutSafe(self.lock());
|
||||
|
||||
@@ -204,39 +225,15 @@ void CLayerSurface::onUnmap() {
|
||||
|
||||
const bool WASLASTFOCUS = g_pCompositor->m_pLastFocus == surface->resource();
|
||||
|
||||
surface.reset();
|
||||
|
||||
if (!PMONITOR)
|
||||
return;
|
||||
|
||||
// refocus if needed
|
||||
if (WASLASTFOCUS) {
|
||||
g_pInputManager->releaseAllMouseButtons();
|
||||
|
||||
Vector2D surfaceCoords;
|
||||
PHLLS pFoundLayerSurface;
|
||||
SP<CWLSurfaceResource> foundSurface = nullptr;
|
||||
|
||||
g_pCompositor->m_pLastFocus.reset();
|
||||
|
||||
// find LS-es to focus
|
||||
foundSurface = g_pCompositor->vectorToLayerSurface(g_pInputManager->getMouseCoordsInternal(), &PMONITOR->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY],
|
||||
&surfaceCoords, &pFoundLayerSurface);
|
||||
|
||||
if (!foundSurface)
|
||||
foundSurface = g_pCompositor->vectorToLayerSurface(g_pInputManager->getMouseCoordsInternal(), &PMONITOR->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_TOP],
|
||||
&surfaceCoords, &pFoundLayerSurface);
|
||||
|
||||
if (!foundSurface && g_pCompositor->m_pLastWindow.lock() && g_pCompositor->isWorkspaceVisible(g_pCompositor->m_pLastWindow->m_pWorkspace)) {
|
||||
// if there isn't any, focus the last window
|
||||
const auto PLASTWINDOW = g_pCompositor->m_pLastWindow.lock();
|
||||
g_pCompositor->focusWindow(nullptr);
|
||||
g_pCompositor->focusWindow(PLASTWINDOW);
|
||||
} else {
|
||||
// otherwise, full refocus
|
||||
g_pInputManager->refocus();
|
||||
}
|
||||
}
|
||||
// vvvvvvvvvvvvv if there is a last focus and the last focus is not keyboard focusable, fallback to window
|
||||
if (WASLASTFOCUS || (g_pCompositor->m_pLastFocus && g_pCompositor->m_pLastFocus->hlSurface && !g_pCompositor->m_pLastFocus->hlSurface->keyboardFocusable()))
|
||||
g_pInputManager->refocusLastWindow(PMONITOR);
|
||||
else if (g_pCompositor->m_pLastFocus)
|
||||
g_pSeatManager->setKeyboardFocus(g_pCompositor->m_pLastFocus.lock());
|
||||
|
||||
CBox geomFixed = {geometry.x + PMONITOR->vecPosition.x, geometry.y + PMONITOR->vecPosition.y, geometry.width, geometry.height};
|
||||
g_pHyprRenderer->damageBox(&geomFixed);
|
||||
@@ -246,12 +243,25 @@ void CLayerSurface::onUnmap() {
|
||||
g_pHyprRenderer->damageBox(&geomFixed);
|
||||
|
||||
g_pInputManager->sendMotionEventsToFocused();
|
||||
|
||||
g_pHyprRenderer->arrangeLayersForMonitor(PMONITOR->ID);
|
||||
}
|
||||
|
||||
void CLayerSurface::onCommit() {
|
||||
if (!layerSurface)
|
||||
return;
|
||||
|
||||
if (!mapped) {
|
||||
// we're re-mapping if this is the case
|
||||
if (layerSurface->surface && !layerSurface->surface->current.texture) {
|
||||
fadingOut = false;
|
||||
geometry = {};
|
||||
g_pHyprRenderer->arrangeLayersForMonitor(monitorID);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(monitorID);
|
||||
|
||||
if (!PMONITOR)
|
||||
@@ -311,18 +321,35 @@ void CLayerSurface::onCommit() {
|
||||
realSize.setValueAndWarp(geometry.size());
|
||||
}
|
||||
|
||||
if (layerSurface->current.interactivity && (g_pSeatManager->mouse.expired() || !g_pInputManager->isConstrained()) // don't focus if constrained
|
||||
&& !keyboardExclusive && mapped) {
|
||||
if (mapped) {
|
||||
const bool WASLASTFOCUS = g_pCompositor->m_pLastFocus == surface->resource();
|
||||
const bool WASEXCLUSIVE = interactivity == ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_EXCLUSIVE;
|
||||
const bool ISEXCLUSIVE = layerSurface->current.interactivity == ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_EXCLUSIVE;
|
||||
|
||||
if (!WASEXCLUSIVE && ISEXCLUSIVE)
|
||||
g_pInputManager->m_dExclusiveLSes.push_back(self);
|
||||
else if (WASEXCLUSIVE && !ISEXCLUSIVE)
|
||||
std::erase_if(g_pInputManager->m_dExclusiveLSes, [this](const auto& other) { return !other.lock() || other.lock() == self.lock(); });
|
||||
|
||||
// if the surface was focused and interactive but now isn't, refocus
|
||||
if (WASLASTFOCUS && !layerSurface->current.interactivity) {
|
||||
// moveMouseUnified won't focus non interactive layers but it won't unfocus them either,
|
||||
// so unfocus the surface here.
|
||||
g_pCompositor->focusSurface(nullptr);
|
||||
g_pInputManager->refocusLastWindow(g_pCompositor->getMonitorFromID(monitorID));
|
||||
} else if (!WASEXCLUSIVE && ISEXCLUSIVE) {
|
||||
// if now exclusive and not previously
|
||||
g_pSeatManager->setGrab(nullptr);
|
||||
g_pInputManager->releaseAllMouseButtons();
|
||||
g_pCompositor->focusSurface(surface->resource());
|
||||
|
||||
const auto LOCAL = g_pInputManager->getMouseCoordsInternal() - Vector2D(geometry.x + PMONITOR->vecPosition.x, geometry.y + PMONITOR->vecPosition.y);
|
||||
g_pSeatManager->setPointerFocus(surface->resource(), LOCAL);
|
||||
g_pInputManager->m_bEmptyFocusCursorSet = false;
|
||||
} else if (!layerSurface->current.interactivity && (g_pSeatManager->mouse.expired() || !g_pInputManager->isConstrained()) && keyboardExclusive) {
|
||||
g_pInputManager->refocus();
|
||||
}
|
||||
}
|
||||
|
||||
keyboardExclusive = layerSurface->current.interactivity;
|
||||
interactivity = layerSurface->current.interactivity;
|
||||
|
||||
g_pHyprRenderer->damageSurface(surface->resource(), position.x, position.y);
|
||||
|
||||
@@ -339,7 +366,7 @@ void CLayerSurface::applyRules() {
|
||||
xray = -1;
|
||||
animationStyle.reset();
|
||||
|
||||
for (auto& rule : g_pConfigManager->getMatchingRules(self.lock())) {
|
||||
for (auto const& rule : g_pConfigManager->getMatchingRules(self.lock())) {
|
||||
if (rule.rule == "noanim")
|
||||
noAnimations = true;
|
||||
else if (rule.rule == "blur")
|
||||
@@ -367,6 +394,11 @@ void CLayerSurface::applyRules() {
|
||||
} else if (rule.rule.starts_with("animation")) {
|
||||
CVarList vars{rule.rule, 2, 's'};
|
||||
animationStyle = vars[1];
|
||||
} else if (rule.rule.starts_with("order")) {
|
||||
CVarList vars{rule.rule, 2, 's'};
|
||||
try {
|
||||
order = std::stoi(vars[1]);
|
||||
} catch (...) { Debug::log(ERR, "Invalid value passed to order"); }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -405,9 +437,9 @@ void CLayerSurface::startAnimation(bool in, bool instant) {
|
||||
}
|
||||
|
||||
const std::array<Vector2D, 4> edgePoints = {
|
||||
PMONITOR->vecPosition + Vector2D{PMONITOR->vecSize.x / 2, 0},
|
||||
PMONITOR->vecPosition + Vector2D{PMONITOR->vecSize.x / 2, 0.0},
|
||||
PMONITOR->vecPosition + Vector2D{PMONITOR->vecSize.x / 2, PMONITOR->vecSize.y},
|
||||
PMONITOR->vecPosition + Vector2D{0, PMONITOR->vecSize.y},
|
||||
PMONITOR->vecPosition + Vector2D{0.0, PMONITOR->vecSize.y},
|
||||
PMONITOR->vecPosition + Vector2D{PMONITOR->vecSize.x, PMONITOR->vecSize.y / 2},
|
||||
};
|
||||
|
||||
|
@@ -34,14 +34,15 @@ class CLayerSurface {
|
||||
WP<CLayerShellResource> layerSurface;
|
||||
wl_list link;
|
||||
|
||||
bool keyboardExclusive = false;
|
||||
// the header providing the enum type cannot be imported here
|
||||
int interactivity = 0;
|
||||
|
||||
SP<CWLSurface> surface;
|
||||
|
||||
bool mapped = false;
|
||||
uint32_t layer = 0;
|
||||
|
||||
int monitorID = -1;
|
||||
MONITORID monitorID = -1;
|
||||
|
||||
bool fadingOut = false;
|
||||
bool readyToDelete = false;
|
||||
@@ -50,10 +51,11 @@ class CLayerSurface {
|
||||
|
||||
bool forceBlur = false;
|
||||
bool forceBlurPopups = false;
|
||||
int xray = -1;
|
||||
int64_t xray = -1;
|
||||
bool ignoreAlpha = false;
|
||||
float ignoreAlphaValue = 0.f;
|
||||
bool dimAround = false;
|
||||
int64_t order = 0;
|
||||
|
||||
std::optional<std::string> animationStyle;
|
||||
|
||||
|
@@ -22,7 +22,7 @@ CPopup::CPopup(SP<CXDGPopupResource> popup, CPopup* pOwner) : m_pParent(pOwner),
|
||||
m_pWindowOwner = pOwner->m_pWindowOwner;
|
||||
|
||||
m_vLastSize = popup->surface->current.geometry.size();
|
||||
unconstrain();
|
||||
reposition();
|
||||
|
||||
initAllSignals();
|
||||
}
|
||||
@@ -55,7 +55,7 @@ void CPopup::initAllSignals() {
|
||||
}
|
||||
|
||||
void CPopup::onNewPopup(SP<CXDGPopupResource> popup) {
|
||||
const auto POPUP = m_vChildren.emplace_back(std::make_unique<CPopup>(popup, this)).get();
|
||||
const auto POPUP = m_vChildren.emplace_back(makeShared<CPopup>(popup, this)).get();
|
||||
Debug::log(LOG, "New popup at {:x}", (uintptr_t)POPUP);
|
||||
}
|
||||
|
||||
@@ -188,18 +188,25 @@ void CPopup::onReposition() {
|
||||
|
||||
m_vLastPos = coordsRelativeToParent();
|
||||
|
||||
unconstrain();
|
||||
reposition();
|
||||
}
|
||||
|
||||
void CPopup::unconstrain() {
|
||||
void CPopup::reposition() {
|
||||
const auto COORDS = t1ParentCoords();
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromVector(COORDS);
|
||||
|
||||
if (!PMONITOR)
|
||||
return;
|
||||
|
||||
CBox box = {PMONITOR->vecPosition.x - COORDS.x, PMONITOR->vecPosition.y - COORDS.y, PMONITOR->vecSize.x, PMONITOR->vecSize.y};
|
||||
m_pResource->applyPositioning(box, COORDS - PMONITOR->vecPosition);
|
||||
CBox box = {PMONITOR->vecPosition.x, PMONITOR->vecPosition.y, PMONITOR->vecSize.x, PMONITOR->vecSize.y};
|
||||
m_pResource->applyPositioning(box, COORDS);
|
||||
}
|
||||
|
||||
SP<CWLSurface> CPopup::getT1Owner() {
|
||||
if (m_pWindowOwner)
|
||||
return m_pWindowOwner->m_pWLSurface;
|
||||
else
|
||||
return m_pLayerOwner->surface;
|
||||
}
|
||||
|
||||
Vector2D CPopup::coordsRelativeToParent() {
|
||||
@@ -250,7 +257,8 @@ void CPopup::recheckTree() {
|
||||
}
|
||||
|
||||
void CPopup::recheckChildrenRecursive() {
|
||||
for (auto& c : m_vChildren) {
|
||||
auto cpy = m_vChildren;
|
||||
for (auto const& c : cpy) {
|
||||
c->onCommit(true);
|
||||
c->recheckChildrenRecursive();
|
||||
}
|
||||
@@ -281,14 +289,14 @@ bool CPopup::visible() {
|
||||
}
|
||||
|
||||
void CPopup::bfHelper(std::vector<CPopup*> nodes, std::function<void(CPopup*, void*)> fn, void* data) {
|
||||
for (auto& n : nodes) {
|
||||
for (auto const& n : nodes) {
|
||||
fn(n, data);
|
||||
}
|
||||
|
||||
std::vector<CPopup*> nodes2;
|
||||
|
||||
for (auto& n : nodes) {
|
||||
for (auto& c : n->m_vChildren) {
|
||||
for (auto const& n : nodes) {
|
||||
for (auto const& c : n->m_vChildren) {
|
||||
nodes2.push_back(c.get());
|
||||
}
|
||||
}
|
||||
@@ -307,7 +315,7 @@ CPopup* CPopup::at(const Vector2D& globalCoords, bool allowsInput) {
|
||||
std::vector<CPopup*> popups;
|
||||
breadthfirst([](CPopup* popup, void* data) { ((std::vector<CPopup*>*)data)->push_back(popup); }, &popups);
|
||||
|
||||
for (auto& p : popups | std::views::reverse) {
|
||||
for (auto const& p : popups | std::views::reverse) {
|
||||
if (!p->m_pResource)
|
||||
continue;
|
||||
|
||||
|
@@ -3,7 +3,7 @@
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include "Subsurface.hpp"
|
||||
#include "../helpers/signal/Listener.hpp"
|
||||
#include "../helpers/signal/Signal.hpp"
|
||||
|
||||
class CXDGPopupResource;
|
||||
|
||||
@@ -18,6 +18,7 @@ class CPopup {
|
||||
|
||||
~CPopup();
|
||||
|
||||
SP<CWLSurface> getT1Owner();
|
||||
Vector2D coordsRelativeToParent();
|
||||
Vector2D coordsGlobal();
|
||||
|
||||
@@ -60,7 +61,7 @@ class CPopup {
|
||||
bool m_bMapped = false;
|
||||
|
||||
//
|
||||
std::vector<std::unique_ptr<CPopup>> m_vChildren;
|
||||
std::vector<SP<CPopup>> m_vChildren;
|
||||
std::unique_ptr<CSubsurface> m_pSubsurfaceHead;
|
||||
|
||||
struct {
|
||||
@@ -74,7 +75,7 @@ class CPopup {
|
||||
} listeners;
|
||||
|
||||
void initAllSignals();
|
||||
void unconstrain();
|
||||
void reposition();
|
||||
void recheckChildrenRecursive();
|
||||
void sendScale();
|
||||
|
||||
|
@@ -30,13 +30,7 @@ CSubsurface::CSubsurface(SP<CWLSubsurfaceResource> pSubsurface, CPopup* pOwner)
|
||||
}
|
||||
|
||||
CSubsurface::~CSubsurface() {
|
||||
hyprListener_newSubsurface.removeCallback();
|
||||
|
||||
if (!m_pSubsurface)
|
||||
return;
|
||||
|
||||
hyprListener_commitSubsurface.removeCallback();
|
||||
hyprListener_destroySubsurface.removeCallback();
|
||||
;
|
||||
}
|
||||
|
||||
void CSubsurface::initSignals() {
|
||||
@@ -65,7 +59,7 @@ void CSubsurface::checkSiblingDamage() {
|
||||
|
||||
const double SCALE = m_pWindowParent.lock() && m_pWindowParent->m_bIsX11 ? 1.0 / m_pWindowParent->m_fX11SurfaceScaledBy : 1.0;
|
||||
|
||||
for (auto& n : m_pParent->m_vChildren) {
|
||||
for (auto const& n : m_pParent->m_vChildren) {
|
||||
if (n.get() == this)
|
||||
continue;
|
||||
|
||||
@@ -75,7 +69,7 @@ void CSubsurface::checkSiblingDamage() {
|
||||
}
|
||||
|
||||
void CSubsurface::recheckDamageForSubsurfaces() {
|
||||
for (auto& n : m_vChildren) {
|
||||
for (auto const& n : m_vChildren) {
|
||||
const auto COORDS = n->coordsGlobal();
|
||||
g_pHyprRenderer->damageSurface(n->m_pWLSurface->resource(), COORDS.x, COORDS.y);
|
||||
}
|
||||
@@ -183,7 +177,7 @@ Vector2D CSubsurface::coordsGlobal() {
|
||||
}
|
||||
|
||||
void CSubsurface::initExistingSubsurfaces(SP<CWLSurfaceResource> pSurface) {
|
||||
for (auto& s : pSurface->subsurfaces) {
|
||||
for (auto const& s : pSurface->subsurfaces) {
|
||||
if (!s || s->surface->hlSurface /* already assigned */)
|
||||
continue;
|
||||
onNewSubsurface(s.lock());
|
||||
|
@@ -35,10 +35,6 @@ class CSubsurface {
|
||||
void recheckDamageForSubsurfaces();
|
||||
|
||||
private:
|
||||
DYNLISTENER(destroySubsurface);
|
||||
DYNLISTENER(commitSubsurface);
|
||||
DYNLISTENER(newSubsurface);
|
||||
|
||||
struct {
|
||||
CHyprSignalListener destroySubsurface;
|
||||
CHyprSignalListener commitSubsurface;
|
||||
|
@@ -1,6 +1,7 @@
|
||||
#include "WLSurface.hpp"
|
||||
#include "../Compositor.hpp"
|
||||
#include "../protocols/core/Compositor.hpp"
|
||||
#include "../protocols/LayerShell.hpp"
|
||||
|
||||
void CWLSurface::assign(SP<CWLSurfaceResource> pSurface) {
|
||||
m_pResource = pSurface;
|
||||
@@ -56,12 +57,12 @@ bool CWLSurface::small() const {
|
||||
if (!validMapped(m_pWindowOwner) || !exists())
|
||||
return false;
|
||||
|
||||
if (!m_pResource->current.buffer)
|
||||
if (!m_pResource->current.texture)
|
||||
return false;
|
||||
|
||||
const auto O = m_pWindowOwner.lock();
|
||||
|
||||
return O->m_vReportedSize.x > m_pResource->current.buffer->size.x + 1 || O->m_vReportedSize.y > m_pResource->current.buffer->size.y + 1;
|
||||
return O->m_vReportedSize.x > m_pResource->current.size.x + 1 || O->m_vReportedSize.y > m_pResource->current.size.y + 1;
|
||||
}
|
||||
|
||||
Vector2D CWLSurface::correctSmallVec() const {
|
||||
@@ -74,33 +75,52 @@ Vector2D CWLSurface::correctSmallVec() const {
|
||||
return Vector2D{(O->m_vReportedSize.x - SIZE.x) / 2, (O->m_vReportedSize.y - SIZE.y) / 2}.clamp({}, {INFINITY, INFINITY}) * (O->m_vRealSize.value() / O->m_vReportedSize);
|
||||
}
|
||||
|
||||
Vector2D CWLSurface::getViewporterCorrectedSize() const {
|
||||
if (!exists() || !m_pResource->current.buffer)
|
||||
Vector2D CWLSurface::correctSmallVecBuf() const {
|
||||
if (!exists() || !small() || m_bFillIgnoreSmall || !m_pResource->current.texture)
|
||||
return {};
|
||||
|
||||
return m_pResource->current.viewport.hasDestination ? m_pResource->current.viewport.destination : m_pResource->current.buffer->size;
|
||||
const auto SIZE = getViewporterCorrectedSize();
|
||||
const auto BS = m_pResource->current.bufferSize;
|
||||
|
||||
return Vector2D{(BS.x - SIZE.x) / 2, (BS.y - SIZE.y) / 2}.clamp({}, {INFINITY, INFINITY});
|
||||
}
|
||||
|
||||
CRegion CWLSurface::logicalDamage() const {
|
||||
if (!m_pResource->current.buffer)
|
||||
Vector2D CWLSurface::getViewporterCorrectedSize() const {
|
||||
if (!exists() || !m_pResource->current.texture)
|
||||
return {};
|
||||
|
||||
return m_pResource->current.viewport.hasDestination ? m_pResource->current.viewport.destination : m_pResource->current.bufferSize;
|
||||
}
|
||||
|
||||
CRegion CWLSurface::computeDamage() const {
|
||||
if (!m_pResource->current.texture)
|
||||
return {};
|
||||
|
||||
CRegion damage = m_pResource->accumulateCurrentBufferDamage();
|
||||
damage.transform(m_pResource->current.transform, m_pResource->current.buffer->size.x, m_pResource->current.buffer->size.y);
|
||||
damage.scale(1.0 / m_pResource->current.scale);
|
||||
damage.transform(wlTransformToHyprutils(m_pResource->current.transform), m_pResource->current.bufferSize.x, m_pResource->current.bufferSize.y);
|
||||
|
||||
const auto VPSIZE = getViewporterCorrectedSize();
|
||||
const auto CORRECTVEC = correctSmallVec();
|
||||
const auto BUFSIZE = m_pResource->current.bufferSize;
|
||||
const auto CORRECTVEC = correctSmallVecBuf();
|
||||
|
||||
if (m_pResource->current.viewport.hasSource)
|
||||
damage.intersect(m_pResource->current.viewport.source);
|
||||
|
||||
const auto SCALEDSRCSIZE =
|
||||
m_pResource->current.viewport.hasSource ? m_pResource->current.viewport.source.size() * m_pResource->current.scale : m_pResource->current.buffer->size;
|
||||
const auto SCALEDSRCSIZE = m_pResource->current.viewport.hasSource ? m_pResource->current.viewport.source.size() * m_pResource->current.scale : m_pResource->current.bufferSize;
|
||||
|
||||
damage.scale({VPSIZE.x / SCALEDSRCSIZE.x, VPSIZE.y / SCALEDSRCSIZE.y});
|
||||
damage.scale({BUFSIZE.x / SCALEDSRCSIZE.x, BUFSIZE.y / SCALEDSRCSIZE.y});
|
||||
damage.translate(CORRECTVEC);
|
||||
|
||||
// go from buffer coords in the damage to hl logical
|
||||
|
||||
const auto BOX = getSurfaceBoxGlobal();
|
||||
const Vector2D SCALE = BOX.has_value() ? BOX->size() / m_pResource->current.bufferSize :
|
||||
Vector2D{1.0 / m_pResource->current.scale, 1.0 / m_pResource->current.scale /* Wrong... but we can't really do better */};
|
||||
|
||||
damage.scale(SCALE);
|
||||
|
||||
if (m_pWindowOwner)
|
||||
damage.scale(m_pWindowOwner->m_fX11SurfaceScaledBy); // fix xwayland:force_zero_scaling stuff that will be fucked by the above a bit
|
||||
|
||||
return damage;
|
||||
}
|
||||
|
||||
@@ -141,27 +161,27 @@ void CWLSurface::init() {
|
||||
Debug::log(LOG, "CWLSurface {:x} called init()", (uintptr_t)this);
|
||||
}
|
||||
|
||||
PHLWINDOW CWLSurface::getWindow() {
|
||||
PHLWINDOW CWLSurface::getWindow() const {
|
||||
return m_pWindowOwner.lock();
|
||||
}
|
||||
|
||||
PHLLS CWLSurface::getLayer() {
|
||||
PHLLS CWLSurface::getLayer() const {
|
||||
return m_pLayerOwner.lock();
|
||||
}
|
||||
|
||||
CPopup* CWLSurface::getPopup() {
|
||||
CPopup* CWLSurface::getPopup() const {
|
||||
return m_pPopupOwner;
|
||||
}
|
||||
|
||||
CSubsurface* CWLSurface::getSubsurface() {
|
||||
CSubsurface* CWLSurface::getSubsurface() const {
|
||||
return m_pSubsurfaceOwner;
|
||||
}
|
||||
|
||||
bool CWLSurface::desktopComponent() {
|
||||
bool CWLSurface::desktopComponent() const {
|
||||
return !m_pLayerOwner.expired() || !m_pWindowOwner.expired() || m_pSubsurfaceOwner || m_pPopupOwner;
|
||||
}
|
||||
|
||||
std::optional<CBox> CWLSurface::getSurfaceBoxGlobal() {
|
||||
std::optional<CBox> CWLSurface::getSurfaceBoxGlobal() const {
|
||||
if (!desktopComponent())
|
||||
return {};
|
||||
|
||||
@@ -181,7 +201,7 @@ void CWLSurface::appendConstraint(WP<CPointerConstraint> constraint) {
|
||||
m_pConstraint = constraint;
|
||||
}
|
||||
|
||||
SP<CPointerConstraint> CWLSurface::constraint() {
|
||||
SP<CPointerConstraint> CWLSurface::constraint() const {
|
||||
return m_pConstraint.lock();
|
||||
}
|
||||
|
||||
@@ -202,3 +222,11 @@ SP<CWLSurface> CWLSurface::fromResource(SP<CWLSurfaceResource> pSurface) {
|
||||
return nullptr;
|
||||
return pSurface->hlSurface.lock();
|
||||
}
|
||||
|
||||
bool CWLSurface::keyboardFocusable() const {
|
||||
if (m_pWindowOwner || m_pPopupOwner || m_pSubsurfaceOwner)
|
||||
return true;
|
||||
if (m_pLayerOwner && m_pLayerOwner->layerSurface)
|
||||
return m_pLayerOwner->layerSurface->current.interactivity != ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_NONE;
|
||||
return false;
|
||||
}
|
||||
|
@@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "../defines.hpp"
|
||||
#include "../helpers/Region.hpp"
|
||||
#include "../helpers/math/Math.hpp"
|
||||
#include "../helpers/signal/Signal.hpp"
|
||||
|
||||
class CSubsurface;
|
||||
@@ -35,20 +35,22 @@ class CWLSurface {
|
||||
bool exists() const;
|
||||
bool small() const; // means surface is smaller than the requested size
|
||||
Vector2D correctSmallVec() const; // returns a corrective vector for small() surfaces
|
||||
Vector2D correctSmallVecBuf() const; // returns a corrective vector for small() surfaces, in BL coords
|
||||
Vector2D getViewporterCorrectedSize() const;
|
||||
CRegion logicalDamage() const;
|
||||
CRegion computeDamage() const; // logical coordinates. May be wrong if the surface is unassigned
|
||||
bool visible();
|
||||
bool keyboardFocusable() const;
|
||||
|
||||
// getters for owners.
|
||||
PHLWINDOW getWindow();
|
||||
PHLLS getLayer();
|
||||
CPopup* getPopup();
|
||||
CSubsurface* getSubsurface();
|
||||
PHLWINDOW getWindow() const;
|
||||
PHLLS getLayer() const;
|
||||
CPopup* getPopup() const;
|
||||
CSubsurface* getSubsurface() const;
|
||||
|
||||
// desktop components misc utils
|
||||
std::optional<CBox> getSurfaceBoxGlobal();
|
||||
std::optional<CBox> getSurfaceBoxGlobal() const;
|
||||
void appendConstraint(WP<CPointerConstraint> constraint);
|
||||
SP<CPointerConstraint> constraint();
|
||||
SP<CPointerConstraint> constraint() const;
|
||||
|
||||
// allow stretching. Useful for plugins.
|
||||
bool m_bFillIgnoreSmall = false;
|
||||
@@ -107,7 +109,7 @@ class CWLSurface {
|
||||
|
||||
void destroy();
|
||||
void init();
|
||||
bool desktopComponent();
|
||||
bool desktopComponent() const;
|
||||
|
||||
struct {
|
||||
CHyprSignalListener destroy;
|
||||
|
@@ -1,4 +1,5 @@
|
||||
#include <any>
|
||||
#include <bit>
|
||||
#include <string_view>
|
||||
#include <algorithm>
|
||||
#include "Window.hpp"
|
||||
@@ -12,12 +13,14 @@
|
||||
#include "../protocols/core/Compositor.hpp"
|
||||
#include "../xwayland/XWayland.hpp"
|
||||
|
||||
#include <hyprutils/string/String.hpp>
|
||||
using namespace Hyprutils::String;
|
||||
|
||||
PHLWINDOW CWindow::create(SP<CXWaylandSurface> surface) {
|
||||
PHLWINDOW pWindow = SP<CWindow>(new CWindow(surface));
|
||||
|
||||
pWindow->m_pSelf = pWindow;
|
||||
pWindow->m_bIsX11 = true;
|
||||
pWindow->m_iX11Type = surface->overrideRedirect ? 2 : 1;
|
||||
|
||||
pWindow->m_vRealPosition.create(g_pConfigManager->getAnimationPropertyConfig("windowsIn"), pWindow, AVARDAMAGE_ENTIRE);
|
||||
pWindow->m_vRealSize.create(g_pConfigManager->getAnimationPropertyConfig("windowsIn"), pWindow, AVARDAMAGE_ENTIRE);
|
||||
@@ -27,6 +30,7 @@ PHLWINDOW CWindow::create(SP<CXWaylandSurface> surface) {
|
||||
pWindow->m_fActiveInactiveAlpha.create(g_pConfigManager->getAnimationPropertyConfig("fadeSwitch"), pWindow, AVARDAMAGE_ENTIRE);
|
||||
pWindow->m_cRealShadowColor.create(g_pConfigManager->getAnimationPropertyConfig("fadeShadow"), pWindow, AVARDAMAGE_SHADOW);
|
||||
pWindow->m_fDimPercent.create(g_pConfigManager->getAnimationPropertyConfig("fadeDim"), pWindow, AVARDAMAGE_ENTIRE);
|
||||
pWindow->m_fMovingToWorkspaceAlpha.create(g_pConfigManager->getAnimationPropertyConfig("fadeOut"), pWindow, AVARDAMAGE_ENTIRE);
|
||||
|
||||
pWindow->addWindowDeco(std::make_unique<CHyprDropShadowDecoration>(pWindow));
|
||||
pWindow->addWindowDeco(std::make_unique<CHyprBorderDecoration>(pWindow));
|
||||
@@ -48,6 +52,7 @@ PHLWINDOW CWindow::create(SP<CXDGSurfaceResource> resource) {
|
||||
pWindow->m_fActiveInactiveAlpha.create(g_pConfigManager->getAnimationPropertyConfig("fadeSwitch"), pWindow, AVARDAMAGE_ENTIRE);
|
||||
pWindow->m_cRealShadowColor.create(g_pConfigManager->getAnimationPropertyConfig("fadeShadow"), pWindow, AVARDAMAGE_SHADOW);
|
||||
pWindow->m_fDimPercent.create(g_pConfigManager->getAnimationPropertyConfig("fadeDim"), pWindow, AVARDAMAGE_ENTIRE);
|
||||
pWindow->m_fMovingToWorkspaceAlpha.create(g_pConfigManager->getAnimationPropertyConfig("fadeOut"), pWindow, AVARDAMAGE_ENTIRE);
|
||||
|
||||
pWindow->addWindowDeco(std::make_unique<CHyprDropShadowDecoration>(pWindow));
|
||||
pWindow->addWindowDeco(std::make_unique<CHyprBorderDecoration>(pWindow));
|
||||
@@ -101,19 +106,19 @@ CWindow::~CWindow() {
|
||||
std::erase_if(g_pHyprOpenGL->m_mWindowFramebuffers, [&](const auto& other) { return !other.first.lock() || other.first.lock().get() == this; });
|
||||
}
|
||||
|
||||
SWindowDecorationExtents CWindow::getFullWindowExtents() {
|
||||
SBoxExtents CWindow::getFullWindowExtents() {
|
||||
if (m_bFadingOut)
|
||||
return m_eOriginalClosedExtents;
|
||||
|
||||
const int BORDERSIZE = getRealBorderSize();
|
||||
|
||||
if (m_sAdditionalConfigData.dimAround) {
|
||||
if (m_sWindowData.dimAround.valueOrDefault()) {
|
||||
if (const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID); PMONITOR)
|
||||
return {{m_vRealPosition.value().x - PMONITOR->vecPosition.x, m_vRealPosition.value().y - PMONITOR->vecPosition.y},
|
||||
{PMONITOR->vecSize.x - (m_vRealPosition.value().x - PMONITOR->vecPosition.x), PMONITOR->vecSize.y - (m_vRealPosition.value().y - PMONITOR->vecPosition.y)}};
|
||||
}
|
||||
|
||||
SWindowDecorationExtents maxExtents = {{BORDERSIZE + 2, BORDERSIZE + 2}, {BORDERSIZE + 2, BORDERSIZE + 2}};
|
||||
SBoxExtents maxExtents = {{BORDERSIZE + 2, BORDERSIZE + 2}, {BORDERSIZE + 2, BORDERSIZE + 2}};
|
||||
|
||||
const auto EXTENTS = g_pDecorationPositioner->getWindowDecorationExtents(m_pSelf.lock());
|
||||
|
||||
@@ -167,7 +172,7 @@ SWindowDecorationExtents CWindow::getFullWindowExtents() {
|
||||
}
|
||||
|
||||
CBox CWindow::getFullWindowBoundingBox() {
|
||||
if (m_sAdditionalConfigData.dimAround) {
|
||||
if (m_sWindowData.dimAround.valueOrDefault()) {
|
||||
if (const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID); PMONITOR)
|
||||
return {PMONITOR->vecPosition.x, PMONITOR->vecPosition.y, PMONITOR->vecSize.x, PMONITOR->vecSize.y};
|
||||
}
|
||||
@@ -189,7 +194,7 @@ CBox CWindow::getWindowIdealBoundingBoxIgnoreReserved() {
|
||||
auto POS = m_vPosition;
|
||||
auto SIZE = m_vSize;
|
||||
|
||||
if (m_bIsFullscreen) {
|
||||
if (isFullscreen()) {
|
||||
POS = PMONITOR->vecPosition;
|
||||
SIZE = PMONITOR->vecSize;
|
||||
|
||||
@@ -215,13 +220,13 @@ CBox CWindow::getWindowIdealBoundingBoxIgnoreReserved() {
|
||||
}
|
||||
|
||||
CBox CWindow::getWindowBoxUnified(uint64_t properties) {
|
||||
if (m_sAdditionalConfigData.dimAround) {
|
||||
if (m_sWindowData.dimAround.valueOrDefault()) {
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
|
||||
if (PMONITOR)
|
||||
return {PMONITOR->vecPosition.x, PMONITOR->vecPosition.y, PMONITOR->vecSize.x, PMONITOR->vecSize.y};
|
||||
}
|
||||
|
||||
SWindowDecorationExtents EXTENTS = {{0, 0}, {0, 0}};
|
||||
SBoxExtents EXTENTS = {{0, 0}, {0, 0}};
|
||||
if (properties & RESERVED_EXTENTS)
|
||||
EXTENTS.addExtents(g_pDecorationPositioner->getWindowDecorationReserved(m_pSelf.lock()));
|
||||
if (properties & INPUT_EXTENTS)
|
||||
@@ -239,7 +244,7 @@ CBox CWindow::getWindowMainSurfaceBox() {
|
||||
return {m_vRealPosition.value().x, m_vRealPosition.value().y, m_vRealSize.value().x, m_vRealSize.value().y};
|
||||
}
|
||||
|
||||
SWindowDecorationExtents CWindow::getFullWindowReservedArea() {
|
||||
SBoxExtents CWindow::getFullWindowReservedArea() {
|
||||
return g_pDecorationPositioner->getWindowDecorationReserved(m_pSelf.lock());
|
||||
}
|
||||
|
||||
@@ -248,7 +253,7 @@ void CWindow::updateWindowDecos() {
|
||||
if (!m_bIsMapped || isHidden())
|
||||
return;
|
||||
|
||||
for (auto& wd : m_vDecosToRemove) {
|
||||
for (auto const& wd : m_vDecosToRemove) {
|
||||
for (auto it = m_dWindowDecorations.begin(); it != m_dWindowDecorations.end(); it++) {
|
||||
if (it->get() == wd) {
|
||||
g_pDecorationPositioner->uncacheDecoration(it->get());
|
||||
@@ -266,11 +271,11 @@ void CWindow::updateWindowDecos() {
|
||||
// make a copy because updateWindow can remove decos.
|
||||
std::vector<IHyprWindowDecoration*> decos;
|
||||
|
||||
for (auto& wd : m_dWindowDecorations) {
|
||||
for (auto const& wd : m_dWindowDecorations) {
|
||||
decos.push_back(wd.get());
|
||||
}
|
||||
|
||||
for (auto& wd : decos) {
|
||||
for (auto const& wd : decos) {
|
||||
if (std::find_if(m_dWindowDecorations.begin(), m_dWindowDecorations.end(), [wd](const auto& other) { return other.get() == wd; }) == m_dWindowDecorations.end())
|
||||
continue;
|
||||
wd->updateWindow(m_pSelf.lock());
|
||||
@@ -292,7 +297,7 @@ void CWindow::removeWindowDeco(IHyprWindowDecoration* deco) {
|
||||
}
|
||||
|
||||
void CWindow::uncacheWindowDecos() {
|
||||
for (auto& wd : m_dWindowDecorations) {
|
||||
for (auto const& wd : m_dWindowDecorations) {
|
||||
g_pDecorationPositioner->uncacheDecoration(wd.get());
|
||||
}
|
||||
}
|
||||
@@ -301,7 +306,7 @@ bool CWindow::checkInputOnDecos(const eInputType type, const Vector2D& mouseCoor
|
||||
if (type != INPUT_TYPE_DRAG_END && hasPopupAt(mouseCoords))
|
||||
return false;
|
||||
|
||||
for (auto& wd : m_dWindowDecorations) {
|
||||
for (auto const& wd : m_dWindowDecorations) {
|
||||
if (!(wd->getDecorationFlags() & DECORATION_ALLOWS_MOUSE_INPUT))
|
||||
continue;
|
||||
|
||||
@@ -333,7 +338,7 @@ pid_t CWindow::getPID() {
|
||||
}
|
||||
|
||||
IHyprWindowDecoration* CWindow::getDecorationByType(eDecorationType type) {
|
||||
for (auto& wd : m_dWindowDecorations) {
|
||||
for (auto const& wd : m_dWindowDecorations) {
|
||||
if (wd->getDecorationType() == type)
|
||||
return wd.get();
|
||||
}
|
||||
@@ -403,16 +408,21 @@ void CWindow::moveToWorkspace(PHLWORKSPACE pWorkspace) {
|
||||
|
||||
const auto OLDWORKSPACE = m_pWorkspace;
|
||||
|
||||
m_iMonitorMovedFrom = OLDWORKSPACE ? OLDWORKSPACE->m_iMonitorID : -1;
|
||||
m_fMovingToWorkspaceAlpha.setValueAndWarp(1.F);
|
||||
m_fMovingToWorkspaceAlpha = 0.F;
|
||||
m_fMovingToWorkspaceAlpha.setCallbackOnEnd([this](void* thisptr) { m_iMonitorMovedFrom = -1; });
|
||||
|
||||
m_pWorkspace = pWorkspace;
|
||||
|
||||
setAnimationsToMove();
|
||||
|
||||
g_pCompositor->updateWorkspaceWindows(OLDWORKSPACE->m_iID);
|
||||
g_pCompositor->updateWorkspaceSpecialRenderData(OLDWORKSPACE->m_iID);
|
||||
g_pCompositor->updateWorkspaceWindowData(OLDWORKSPACE->m_iID);
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(OLDWORKSPACE->m_iMonitorID);
|
||||
|
||||
g_pCompositor->updateWorkspaceWindows(workspaceID());
|
||||
g_pCompositor->updateWorkspaceSpecialRenderData(workspaceID());
|
||||
g_pCompositor->updateWorkspaceWindowData(workspaceID());
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m_iMonitorID);
|
||||
|
||||
g_pCompositor->updateAllWindowsAnimatedDecorationValues();
|
||||
@@ -442,13 +452,15 @@ PHLWINDOW CWindow::X11TransientFor() {
|
||||
return nullptr;
|
||||
|
||||
auto s = m_pXWaylandSurface->parent;
|
||||
auto oldParent = s;
|
||||
while (s) {
|
||||
if (!s->parent)
|
||||
// break cyclic loop of m_pXWaylandSurface being parent of itself, #TODO reject this from even being created?
|
||||
if (!s->parent || s->parent == oldParent)
|
||||
break;
|
||||
s = s->parent;
|
||||
}
|
||||
|
||||
for (auto& w : g_pCompositor->m_vWindows) {
|
||||
for (auto const& w : g_pCompositor->m_vWindows) {
|
||||
if (w->m_pXWaylandSurface != s)
|
||||
continue;
|
||||
return w;
|
||||
@@ -458,7 +470,7 @@ PHLWINDOW CWindow::X11TransientFor() {
|
||||
}
|
||||
|
||||
void CWindow::removeDecorationByType(eDecorationType type) {
|
||||
for (auto& wd : m_dWindowDecorations) {
|
||||
for (auto const& wd : m_dWindowDecorations) {
|
||||
if (wd->getDecorationType() == type)
|
||||
m_vDecosToRemove.push_back(wd.get());
|
||||
}
|
||||
@@ -472,12 +484,6 @@ void unregisterVar(void* ptr) {
|
||||
|
||||
void CWindow::onUnmap() {
|
||||
static auto PCLOSEONLASTSPECIAL = CConfigValue<Hyprlang::INT>("misc:close_special_on_empty");
|
||||
|
||||
if (g_pCompositor->m_pLastWindow.lock().get() == this)
|
||||
g_pCompositor->m_pLastWindow.reset();
|
||||
if (g_pInputManager->currentlyDraggedWindow.lock().get() == this)
|
||||
g_pInputManager->currentlyDraggedWindow.reset();
|
||||
|
||||
static auto PINITIALWSTRACKING = CConfigValue<Hyprlang::INT>("misc:initial_workspace_tracking");
|
||||
|
||||
if (!m_szInitialWorkspaceToken.empty()) {
|
||||
@@ -502,6 +508,7 @@ void CWindow::onUnmap() {
|
||||
m_fAlpha.setCallbackOnEnd(unregisterVar);
|
||||
m_cRealShadowColor.setCallbackOnEnd(unregisterVar);
|
||||
m_fDimPercent.setCallbackOnEnd(unregisterVar);
|
||||
m_fMovingToWorkspaceAlpha.setCallbackOnEnd(unregisterVar);
|
||||
|
||||
m_vRealSize.setCallbackOnBegin(nullptr);
|
||||
|
||||
@@ -519,7 +526,7 @@ void CWindow::onUnmap() {
|
||||
PMONITOR->solitaryClient.reset();
|
||||
|
||||
g_pCompositor->updateWorkspaceWindows(workspaceID());
|
||||
g_pCompositor->updateWorkspaceSpecialRenderData(workspaceID());
|
||||
g_pCompositor->updateWorkspaceWindowData(workspaceID());
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m_iMonitorID);
|
||||
g_pCompositor->updateAllWindowsAnimatedDecorationValues();
|
||||
|
||||
@@ -542,6 +549,7 @@ void CWindow::onMap() {
|
||||
m_fAlpha.resetAllCallbacks();
|
||||
m_cRealShadowColor.resetAllCallbacks();
|
||||
m_fDimPercent.resetAllCallbacks();
|
||||
m_fMovingToWorkspaceAlpha.resetAllCallbacks();
|
||||
|
||||
m_vRealPosition.registerVar();
|
||||
m_vRealSize.registerVar();
|
||||
@@ -551,6 +559,7 @@ void CWindow::onMap() {
|
||||
m_fAlpha.registerVar();
|
||||
m_cRealShadowColor.registerVar();
|
||||
m_fDimPercent.registerVar();
|
||||
m_fMovingToWorkspaceAlpha.registerVar();
|
||||
|
||||
m_fBorderAngleAnimationProgress.setCallbackOnEnd([&](void* ptr) { onBorderAngleAnimEnd(ptr); }, false);
|
||||
|
||||
@@ -602,65 +611,39 @@ bool CWindow::isHidden() {
|
||||
}
|
||||
|
||||
void CWindow::applyDynamicRule(const SWindowRule& r) {
|
||||
if (r.szRule == "noblur") {
|
||||
m_sAdditionalConfigData.forceNoBlur = true;
|
||||
} else if (r.szRule == "noborder") {
|
||||
m_sAdditionalConfigData.forceNoBorder = true;
|
||||
} else if (r.szRule == "noshadow") {
|
||||
m_sAdditionalConfigData.forceNoShadow = true;
|
||||
} else if (r.szRule == "nodim") {
|
||||
m_sAdditionalConfigData.forceNoDim = true;
|
||||
} else if (r.szRule == "forcergbx") {
|
||||
m_sAdditionalConfigData.forceRGBX = true;
|
||||
} else if (r.szRule == "opaque") {
|
||||
if (!m_sAdditionalConfigData.forceOpaqueOverridden)
|
||||
m_sAdditionalConfigData.forceOpaque = true;
|
||||
} else if (r.szRule == "immediate") {
|
||||
m_sAdditionalConfigData.forceTearing = true;
|
||||
} else if (r.szRule == "nearestneighbor") {
|
||||
m_sAdditionalConfigData.nearestNeighbor = true;
|
||||
} else if (r.szRule.starts_with("tag")) {
|
||||
const eOverridePriority priority = r.szValue == "execRule" ? PRIORITY_SET_PROP : PRIORITY_WINDOW_RULE;
|
||||
const CVarList VARS(r.szRule, 0, ' ');
|
||||
if (r.szRule.starts_with("tag")) {
|
||||
CVarList vars{r.szRule, 0, 's', true};
|
||||
|
||||
if (vars.size() == 2 && vars[0] == "tag")
|
||||
m_tags.applyTag(vars[1], true);
|
||||
else
|
||||
Debug::log(ERR, "Tag rule invalid: {}", r.szRule);
|
||||
} else if (r.szRule.starts_with("rounding")) {
|
||||
try {
|
||||
m_sAdditionalConfigData.rounding = std::stoi(r.szRule.substr(r.szRule.find_first_of(' ') + 1));
|
||||
} catch (std::exception& e) { Debug::log(ERR, "Rounding rule \"{}\" failed with: {}", r.szRule, e.what()); }
|
||||
} else if (r.szRule.starts_with("bordersize")) {
|
||||
try {
|
||||
m_sAdditionalConfigData.borderSize = std::stoi(r.szRule.substr(r.szRule.find_first_of(' ') + 1));
|
||||
} catch (std::exception& e) { Debug::log(ERR, "Bordersize rule \"{}\" failed with: {}", r.szRule, e.what()); }
|
||||
} else if (r.szRule.starts_with("opacity")) {
|
||||
try {
|
||||
CVarList vars(r.szRule, 0, ' ');
|
||||
|
||||
int opacityIDX = 0;
|
||||
|
||||
for (auto& r : vars) {
|
||||
for (auto const& r : vars) {
|
||||
if (r == "opacity")
|
||||
continue;
|
||||
|
||||
if (r == "override") {
|
||||
if (opacityIDX == 1)
|
||||
m_sSpecialRenderData.alphaOverride = true;
|
||||
m_sWindowData.alpha = CWindowOverridableVar(SAlphaValue{m_sWindowData.alpha.value().m_fAlpha, true}, priority);
|
||||
else if (opacityIDX == 2)
|
||||
m_sSpecialRenderData.alphaInactiveOverride = true;
|
||||
m_sWindowData.alphaInactive = CWindowOverridableVar(SAlphaValue{m_sWindowData.alphaInactive.value().m_fAlpha, true}, priority);
|
||||
else if (opacityIDX == 3)
|
||||
m_sSpecialRenderData.alphaFullscreenOverride = true;
|
||||
m_sWindowData.alphaFullscreen = CWindowOverridableVar(SAlphaValue{m_sWindowData.alphaFullscreen.value().m_fAlpha, true}, priority);
|
||||
} else {
|
||||
if (opacityIDX == 0) {
|
||||
m_sSpecialRenderData.alpha = std::stof(r);
|
||||
m_sSpecialRenderData.alphaOverride = false;
|
||||
m_sWindowData.alpha = CWindowOverridableVar(SAlphaValue{std::stof(r), false}, priority);
|
||||
} else if (opacityIDX == 1) {
|
||||
m_sSpecialRenderData.alphaInactive = std::stof(r);
|
||||
m_sSpecialRenderData.alphaInactiveOverride = false;
|
||||
m_sWindowData.alphaInactive = CWindowOverridableVar(SAlphaValue{std::stof(r), false}, priority);
|
||||
} else if (opacityIDX == 2) {
|
||||
m_sSpecialRenderData.alphaFullscreen = std::stof(r);
|
||||
m_sSpecialRenderData.alphaFullscreenOverride = false;
|
||||
m_sWindowData.alphaFullscreen = CWindowOverridableVar(SAlphaValue{std::stof(r), false}, priority);
|
||||
} else {
|
||||
throw std::runtime_error("more than 3 alpha values");
|
||||
}
|
||||
@@ -670,33 +653,29 @@ void CWindow::applyDynamicRule(const SWindowRule& r) {
|
||||
}
|
||||
|
||||
if (opacityIDX == 1) {
|
||||
m_sSpecialRenderData.alphaInactiveOverride = m_sSpecialRenderData.alphaOverride;
|
||||
m_sSpecialRenderData.alphaInactive = m_sSpecialRenderData.alpha;
|
||||
m_sSpecialRenderData.alphaFullscreenOverride = m_sSpecialRenderData.alphaOverride;
|
||||
m_sSpecialRenderData.alphaFullscreen = m_sSpecialRenderData.alpha;
|
||||
m_sWindowData.alphaInactive = m_sWindowData.alpha;
|
||||
m_sWindowData.alphaFullscreen = m_sWindowData.alpha;
|
||||
}
|
||||
} catch (std::exception& e) { Debug::log(ERR, "Opacity rule \"{}\" failed with: {}", r.szRule, e.what()); }
|
||||
} else if (r.szRule == "noanim") {
|
||||
m_sAdditionalConfigData.forceNoAnims = true;
|
||||
} else if (r.szRule.starts_with("animation")) {
|
||||
auto STYLE = r.szRule.substr(r.szRule.find_first_of(' ') + 1);
|
||||
m_sAdditionalConfigData.animationStyle = STYLE;
|
||||
m_sWindowData.animationStyle = CWindowOverridableVar(STYLE, priority);
|
||||
} else if (r.szRule.starts_with("bordercolor")) {
|
||||
try {
|
||||
// Each vector will only get used if it has at least one color
|
||||
CGradientValueData activeBorderGradient = {};
|
||||
CGradientValueData inactiveBorderGradient = {};
|
||||
bool active = true;
|
||||
CVarList colorsAndAngles = CVarList(removeBeginEndSpacesTabs(r.szRule.substr(r.szRule.find_first_of(' ') + 1)), 0, 's', true);
|
||||
CVarList colorsAndAngles = CVarList(trim(r.szRule.substr(r.szRule.find_first_of(' ') + 1)), 0, 's', true);
|
||||
|
||||
// Basic form has only two colors, everything else can be parsed as a gradient
|
||||
if (colorsAndAngles.size() == 2 && !colorsAndAngles[1].contains("deg")) {
|
||||
m_sSpecialRenderData.activeBorderColor = CGradientValueData(CColor(configStringToInt(colorsAndAngles[0])));
|
||||
m_sSpecialRenderData.inactiveBorderColor = CGradientValueData(CColor(configStringToInt(colorsAndAngles[1])));
|
||||
m_sWindowData.activeBorderColor = CWindowOverridableVar(CGradientValueData(CColor(configStringToInt(colorsAndAngles[0]))), priority);
|
||||
m_sWindowData.inactiveBorderColor = CWindowOverridableVar(CGradientValueData(CColor(configStringToInt(colorsAndAngles[1]))), priority);
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto& token : colorsAndAngles) {
|
||||
for (auto const& token : colorsAndAngles) {
|
||||
// The first angle, or an explicit "0deg", splits the two gradients
|
||||
if (active && token.contains("deg")) {
|
||||
activeBorderGradient.m_fAngle = std::stoi(token.substr(0, token.size() - 3)) * (PI / 180.0);
|
||||
@@ -715,24 +694,24 @@ void CWindow::applyDynamicRule(const SWindowRule& r) {
|
||||
else if (activeBorderGradient.m_vColors.empty())
|
||||
Debug::log(WARN, "Bordercolor rule \"{}\" has no colors, ignoring", r.szRule);
|
||||
else if (inactiveBorderGradient.m_vColors.empty())
|
||||
m_sSpecialRenderData.activeBorderColor = activeBorderGradient;
|
||||
m_sWindowData.activeBorderColor = CWindowOverridableVar(activeBorderGradient, priority);
|
||||
else {
|
||||
m_sSpecialRenderData.activeBorderColor = activeBorderGradient;
|
||||
m_sSpecialRenderData.inactiveBorderColor = inactiveBorderGradient;
|
||||
m_sWindowData.activeBorderColor = CWindowOverridableVar(activeBorderGradient, priority);
|
||||
m_sWindowData.inactiveBorderColor = CWindowOverridableVar(inactiveBorderGradient, priority);
|
||||
}
|
||||
} catch (std::exception& e) { Debug::log(ERR, "BorderColor rule \"{}\" failed with: {}", r.szRule, e.what()); }
|
||||
} else if (r.szRule == "dimaround") {
|
||||
m_sAdditionalConfigData.dimAround = true;
|
||||
} else if (r.szRule == "keepaspectratio") {
|
||||
m_sAdditionalConfigData.keepAspectRatio = true;
|
||||
} else if (r.szRule.starts_with("focusonactivate")) {
|
||||
m_sAdditionalConfigData.focusOnActivate = true;
|
||||
} else if (r.szRule.starts_with("xray")) {
|
||||
CVarList vars(r.szRule, 0, ' ');
|
||||
|
||||
} else if (auto search = g_pConfigManager->mbWindowProperties.find(VARS[0]); search != g_pConfigManager->mbWindowProperties.end()) {
|
||||
if (VARS[1].empty()) {
|
||||
*(search->second(m_pSelf.lock())) = CWindowOverridableVar(true, priority);
|
||||
} else {
|
||||
try {
|
||||
m_sAdditionalConfigData.xray = configStringToInt(vars[1]);
|
||||
*(search->second(m_pSelf.lock())) = CWindowOverridableVar((bool)configStringToInt(VARS[1]), priority);
|
||||
} catch (...) {}
|
||||
}
|
||||
} else if (auto search = g_pConfigManager->miWindowProperties.find(VARS[0]); search != g_pConfigManager->miWindowProperties.end()) {
|
||||
try {
|
||||
*(search->second(m_pSelf.lock())) = CWindowOverridableVar(std::stoi(VARS[1]), priority);
|
||||
} catch (std::exception& e) { Debug::log(ERR, "Rule \"{}\" failed with: {}", r.szRule, e.what()); }
|
||||
} else if (r.szRule.starts_with("idleinhibit")) {
|
||||
auto IDLERULE = r.szRule.substr(r.szRule.find_first_of(' ') + 1);
|
||||
|
||||
@@ -756,9 +735,9 @@ void CWindow::applyDynamicRule(const SWindowRule& r) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_sAdditionalConfigData.maxSize = VEC;
|
||||
m_vRealSize = Vector2D(std::min((double)m_sAdditionalConfigData.maxSize.toUnderlying().x, m_vRealSize.goal().x),
|
||||
std::min((double)m_sAdditionalConfigData.maxSize.toUnderlying().y, m_vRealSize.goal().y));
|
||||
m_sWindowData.maxSize = CWindowOverridableVar(VEC, priority);
|
||||
m_vRealSize =
|
||||
Vector2D(std::min((double)m_sWindowData.maxSize.value().x, m_vRealSize.goal().x), std::min((double)m_sWindowData.maxSize.value().y, m_vRealSize.goal().y));
|
||||
g_pXWaylandManager->setWindowSize(m_pSelf.lock(), m_vRealSize.goal());
|
||||
} catch (std::exception& e) { Debug::log(ERR, "maxsize rule \"{}\" failed with: {}", r.szRule, e.what()); }
|
||||
} else if (r.szRule.starts_with("minsize")) {
|
||||
@@ -771,46 +750,41 @@ void CWindow::applyDynamicRule(const SWindowRule& r) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_sAdditionalConfigData.minSize = VEC;
|
||||
m_vRealSize = Vector2D(std::max((double)m_sAdditionalConfigData.minSize.toUnderlying().x, m_vRealSize.goal().x),
|
||||
std::max((double)m_sAdditionalConfigData.minSize.toUnderlying().y, m_vRealSize.goal().y));
|
||||
m_sWindowData.minSize = CWindowOverridableVar(VEC, priority);
|
||||
m_vRealSize =
|
||||
Vector2D(std::max((double)m_sWindowData.minSize.value().x, m_vRealSize.goal().x), std::max((double)m_sWindowData.minSize.value().y, m_vRealSize.goal().y));
|
||||
g_pXWaylandManager->setWindowSize(m_pSelf.lock(), m_vRealSize.goal());
|
||||
if (m_sGroupData.pNextWindow.expired())
|
||||
setHidden(false);
|
||||
} catch (std::exception& e) { Debug::log(ERR, "minsize rule \"{}\" failed with: {}", r.szRule, e.what()); }
|
||||
} else if (r.szRule == "renderunfocused") {
|
||||
m_sWindowData.renderUnfocused = CWindowOverridableVar(true, priority);
|
||||
g_pHyprRenderer->addWindowToRenderUnfocused(m_pSelf.lock());
|
||||
}
|
||||
}
|
||||
|
||||
void CWindow::updateDynamicRules() {
|
||||
m_sSpecialRenderData.activeBorderColor = CGradientValueData();
|
||||
m_sSpecialRenderData.inactiveBorderColor = CGradientValueData();
|
||||
m_sSpecialRenderData.alpha = 1.f;
|
||||
m_sSpecialRenderData.alphaInactive = -1.f;
|
||||
m_sAdditionalConfigData.forceNoBlur = false;
|
||||
m_sAdditionalConfigData.forceNoBorder = false;
|
||||
m_sAdditionalConfigData.forceNoShadow = false;
|
||||
m_sAdditionalConfigData.forceNoDim = false;
|
||||
if (!m_sAdditionalConfigData.forceOpaqueOverridden)
|
||||
m_sAdditionalConfigData.forceOpaque = false;
|
||||
m_sAdditionalConfigData.maxSize = Vector2D(std::numeric_limits<double>::max(), std::numeric_limits<double>::max());
|
||||
m_sAdditionalConfigData.minSize = Vector2D(20, 20);
|
||||
m_sAdditionalConfigData.forceNoAnims = false;
|
||||
m_sAdditionalConfigData.animationStyle = std::string("");
|
||||
m_sAdditionalConfigData.rounding = -1;
|
||||
m_sAdditionalConfigData.dimAround = false;
|
||||
m_sAdditionalConfigData.forceRGBX = false;
|
||||
m_sAdditionalConfigData.borderSize = -1;
|
||||
m_sAdditionalConfigData.keepAspectRatio = false;
|
||||
m_sAdditionalConfigData.focusOnActivate = false;
|
||||
m_sAdditionalConfigData.xray = -1;
|
||||
m_sAdditionalConfigData.forceTearing = false;
|
||||
m_sAdditionalConfigData.nearestNeighbor = false;
|
||||
m_sWindowData.alpha.unset(PRIORITY_WINDOW_RULE);
|
||||
m_sWindowData.alphaInactive.unset(PRIORITY_WINDOW_RULE);
|
||||
m_sWindowData.alphaFullscreen.unset(PRIORITY_WINDOW_RULE);
|
||||
|
||||
unsetWindowData(PRIORITY_WINDOW_RULE);
|
||||
|
||||
m_sWindowData.animationStyle.unset(PRIORITY_WINDOW_RULE);
|
||||
m_sWindowData.maxSize.unset(PRIORITY_WINDOW_RULE);
|
||||
m_sWindowData.minSize.unset(PRIORITY_WINDOW_RULE);
|
||||
|
||||
m_sWindowData.activeBorderColor.unset(PRIORITY_WINDOW_RULE);
|
||||
m_sWindowData.inactiveBorderColor.unset(PRIORITY_WINDOW_RULE);
|
||||
|
||||
m_sWindowData.renderUnfocused.unset(PRIORITY_WINDOW_RULE);
|
||||
|
||||
m_eIdleInhibitMode = IDLEINHIBIT_NONE;
|
||||
|
||||
m_tags.removeDynamicTags();
|
||||
|
||||
m_vMatchedRules = g_pConfigManager->getMatchingRules(m_pSelf.lock());
|
||||
for (auto& r : m_vMatchedRules) {
|
||||
for (auto const& r : m_vMatchedRules) {
|
||||
applyDynamicRule(r);
|
||||
}
|
||||
|
||||
@@ -882,7 +856,7 @@ void CWindow::createGroup() {
|
||||
addWindowDeco(std::make_unique<CHyprGroupBarDecoration>(m_pSelf.lock()));
|
||||
|
||||
g_pCompositor->updateWorkspaceWindows(workspaceID());
|
||||
g_pCompositor->updateWorkspaceSpecialRenderData(workspaceID());
|
||||
g_pCompositor->updateWorkspaceWindowData(workspaceID());
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m_iMonitorID);
|
||||
g_pCompositor->updateAllWindowsAnimatedDecorationValues();
|
||||
|
||||
@@ -900,7 +874,7 @@ void CWindow::destroyGroup() {
|
||||
m_sGroupData.head = false;
|
||||
updateWindowDecos();
|
||||
g_pCompositor->updateWorkspaceWindows(workspaceID());
|
||||
g_pCompositor->updateWorkspaceSpecialRenderData(workspaceID());
|
||||
g_pCompositor->updateWorkspaceWindowData(workspaceID());
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m_iMonitorID);
|
||||
g_pCompositor->updateAllWindowsAnimatedDecorationValues();
|
||||
|
||||
@@ -921,7 +895,7 @@ void CWindow::destroyGroup() {
|
||||
addresses += std::format("{:x},", (uintptr_t)curr.get());
|
||||
} while (curr.get() != this);
|
||||
|
||||
for (auto& w : members) {
|
||||
for (auto const& w : members) {
|
||||
if (w->m_sGroupData.head)
|
||||
g_pLayoutManager->getCurrentLayout()->onWindowRemoved(curr);
|
||||
w->m_sGroupData.head = false;
|
||||
@@ -929,14 +903,14 @@ void CWindow::destroyGroup() {
|
||||
|
||||
const bool GROUPSLOCKEDPREV = g_pKeybindManager->m_bGroupsLocked;
|
||||
g_pKeybindManager->m_bGroupsLocked = true;
|
||||
for (auto& w : members) {
|
||||
for (auto const& w : members) {
|
||||
g_pLayoutManager->getCurrentLayout()->onWindowCreated(w);
|
||||
w->updateWindowDecos();
|
||||
}
|
||||
g_pKeybindManager->m_bGroupsLocked = GROUPSLOCKEDPREV;
|
||||
|
||||
g_pCompositor->updateWorkspaceWindows(workspaceID());
|
||||
g_pCompositor->updateWorkspaceSpecialRenderData(workspaceID());
|
||||
g_pCompositor->updateWorkspaceWindowData(workspaceID());
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m_iMonitorID);
|
||||
g_pCompositor->updateAllWindowsAnimatedDecorationValues();
|
||||
|
||||
@@ -977,12 +951,16 @@ int CWindow::getGroupSize() {
|
||||
}
|
||||
|
||||
bool CWindow::canBeGroupedInto(PHLWINDOW pWindow) {
|
||||
static auto ALLOWGROUPMERGE = CConfigValue<Hyprlang::INT>("group:merge_groups_on_drag");
|
||||
bool isGroup = m_sGroupData.pNextWindow;
|
||||
bool disallowDragIntoGroup = g_pInputManager->m_bWasDraggingWindow && isGroup && !bool(*ALLOWGROUPMERGE);
|
||||
return !g_pKeybindManager->m_bGroupsLocked // global group lock disengaged
|
||||
&& ((m_eGroupRules & GROUP_INVADE && m_bFirstMap) // window ignore local group locks, or
|
||||
|| (!pWindow->getGroupHead()->m_sGroupData.locked // target unlocked
|
||||
&& !(m_sGroupData.pNextWindow.lock() && getGroupHead()->m_sGroupData.locked))) // source unlocked or isn't group
|
||||
&& !m_sGroupData.deny // source is not denied entry
|
||||
&& !(m_eGroupRules & GROUP_BARRED && m_bFirstMap); // group rule doesn't prevent adding window
|
||||
&& !(m_eGroupRules & GROUP_BARRED && m_bFirstMap) // group rule doesn't prevent adding window
|
||||
&& !disallowDragIntoGroup; // config allows groups to be merged
|
||||
}
|
||||
|
||||
PHLWINDOW CWindow::getGroupWindowByIndex(int index) {
|
||||
@@ -1011,8 +989,9 @@ void CWindow::setGroupCurrent(PHLWINDOW pWindow) {
|
||||
return;
|
||||
|
||||
const auto PCURRENT = getGroupCurrent();
|
||||
const bool FULLSCREEN = PCURRENT->m_bIsFullscreen;
|
||||
const bool FULLSCREEN = PCURRENT->isFullscreen();
|
||||
const auto WORKSPACE = PCURRENT->m_pWorkspace;
|
||||
const auto MODE = PCURRENT->m_sFullscreenState.internal;
|
||||
|
||||
const auto PWINDOWSIZE = PCURRENT->m_vRealSize.goal();
|
||||
const auto PWINDOWPOS = PCURRENT->m_vRealPosition.goal();
|
||||
@@ -1020,7 +999,7 @@ void CWindow::setGroupCurrent(PHLWINDOW pWindow) {
|
||||
const auto CURRENTISFOCUS = PCURRENT == g_pCompositor->m_pLastWindow.lock();
|
||||
|
||||
if (FULLSCREEN)
|
||||
g_pCompositor->setWindowFullscreen(PCURRENT, false, WORKSPACE->m_efFullscreenMode);
|
||||
g_pCompositor->setWindowFullscreenInternal(PCURRENT, FSMODE_NONE);
|
||||
|
||||
PCURRENT->setHidden(true);
|
||||
pWindow->setHidden(false); // can remove m_pLastWindow
|
||||
@@ -1038,7 +1017,7 @@ void CWindow::setGroupCurrent(PHLWINDOW pWindow) {
|
||||
g_pCompositor->focusWindow(pWindow);
|
||||
|
||||
if (FULLSCREEN)
|
||||
g_pCompositor->setWindowFullscreen(pWindow, true, WORKSPACE->m_efFullscreenMode);
|
||||
g_pCompositor->setWindowFullscreenInternal(pWindow, MODE);
|
||||
|
||||
g_pHyprRenderer->damageWindow(pWindow);
|
||||
|
||||
@@ -1137,70 +1116,61 @@ bool CWindow::opaque() {
|
||||
if (PWORKSPACE->m_fAlpha.value() != 1.f)
|
||||
return false;
|
||||
|
||||
if (m_bIsX11 && m_pXWaylandSurface && m_pXWaylandSurface->surface && m_pXWaylandSurface->surface->current.buffer)
|
||||
return m_pXWaylandSurface->surface->current.buffer->opaque;
|
||||
if (m_bIsX11 && m_pXWaylandSurface && m_pXWaylandSurface->surface && m_pXWaylandSurface->surface->current.texture)
|
||||
return m_pXWaylandSurface->surface->current.texture->m_bOpaque;
|
||||
|
||||
if (!m_pWLSurface->resource() || !m_pWLSurface->resource()->current.buffer)
|
||||
if (!m_pWLSurface->resource() || !m_pWLSurface->resource()->current.texture)
|
||||
return false;
|
||||
|
||||
// TODO: this is wrong
|
||||
const auto EXTENTS = m_pXDGSurface->surface->current.opaque.getExtents();
|
||||
if (EXTENTS.w >= m_pXDGSurface->surface->current.buffer->size.x && EXTENTS.h >= m_pXDGSurface->surface->current.buffer->size.y)
|
||||
if (EXTENTS.w >= m_pXDGSurface->surface->current.bufferSize.x && EXTENTS.h >= m_pXDGSurface->surface->current.bufferSize.y)
|
||||
return true;
|
||||
|
||||
return m_pWLSurface->resource()->current.buffer->opaque;
|
||||
return m_pWLSurface->resource()->current.texture->m_bOpaque;
|
||||
}
|
||||
|
||||
float CWindow::rounding() {
|
||||
static auto PROUNDING = CConfigValue<Hyprlang::INT>("decoration:rounding");
|
||||
|
||||
float rounding = m_sAdditionalConfigData.rounding.toUnderlying() == -1 ? *PROUNDING : m_sAdditionalConfigData.rounding.toUnderlying();
|
||||
float rounding = m_sWindowData.rounding.valueOr(*PROUNDING);
|
||||
|
||||
return m_sSpecialRenderData.rounding ? rounding : 0;
|
||||
return m_sWindowData.noRounding.valueOrDefault() ? 0 : rounding;
|
||||
}
|
||||
|
||||
void CWindow::updateSpecialRenderData() {
|
||||
void CWindow::updateWindowData() {
|
||||
const auto PWORKSPACE = m_pWorkspace;
|
||||
const auto WORKSPACERULE = PWORKSPACE ? g_pConfigManager->getWorkspaceRuleFor(PWORKSPACE) : SWorkspaceRule{};
|
||||
updateSpecialRenderData(WORKSPACERULE);
|
||||
updateWindowData(WORKSPACERULE);
|
||||
}
|
||||
|
||||
void CWindow::updateSpecialRenderData(const SWorkspaceRule& workspaceRule) {
|
||||
void CWindow::updateWindowData(const SWorkspaceRule& workspaceRule) {
|
||||
static auto PNOBORDERONFLOATING = CConfigValue<Hyprlang::INT>("general:no_border_on_floating");
|
||||
|
||||
bool border = true;
|
||||
if (m_bIsFloating && *PNOBORDERONFLOATING == 1)
|
||||
border = false;
|
||||
if (*PNOBORDERONFLOATING)
|
||||
m_sWindowData.noBorder = CWindowOverridableVar(m_bIsFloating, PRIORITY_LAYOUT);
|
||||
else
|
||||
m_sWindowData.noBorder.unset(PRIORITY_LAYOUT);
|
||||
|
||||
m_sSpecialRenderData.border = workspaceRule.border.value_or(border);
|
||||
m_sSpecialRenderData.borderSize = workspaceRule.borderSize.value_or(-1);
|
||||
m_sSpecialRenderData.decorate = workspaceRule.decorate.value_or(true);
|
||||
m_sSpecialRenderData.rounding = workspaceRule.rounding.value_or(true);
|
||||
m_sSpecialRenderData.shadow = workspaceRule.shadow.value_or(true);
|
||||
m_sWindowData.borderSize.matchOptional(workspaceRule.borderSize, PRIORITY_WORKSPACE_RULE);
|
||||
m_sWindowData.decorate.matchOptional(workspaceRule.decorate, PRIORITY_WORKSPACE_RULE);
|
||||
m_sWindowData.noBorder.matchOptional(workspaceRule.noBorder, PRIORITY_WORKSPACE_RULE);
|
||||
m_sWindowData.noRounding.matchOptional(workspaceRule.noRounding, PRIORITY_WORKSPACE_RULE);
|
||||
m_sWindowData.noShadow.matchOptional(workspaceRule.noShadow, PRIORITY_WORKSPACE_RULE);
|
||||
}
|
||||
|
||||
int CWindow::getRealBorderSize() {
|
||||
if (!m_sSpecialRenderData.border || m_sAdditionalConfigData.forceNoBorder || (m_pWorkspace && m_bIsFullscreen && (m_pWorkspace->m_efFullscreenMode == FULLSCREEN_FULL)))
|
||||
if (m_sWindowData.noBorder.valueOrDefault() || (m_pWorkspace && isEffectiveInternalFSMode(FSMODE_FULLSCREEN)))
|
||||
return 0;
|
||||
|
||||
if (m_sAdditionalConfigData.borderSize.toUnderlying() != -1)
|
||||
return m_sAdditionalConfigData.borderSize.toUnderlying();
|
||||
|
||||
if (m_sSpecialRenderData.borderSize.toUnderlying() != -1)
|
||||
return m_sSpecialRenderData.borderSize.toUnderlying();
|
||||
|
||||
static auto PBORDERSIZE = CConfigValue<Hyprlang::INT>("general:border_size");
|
||||
|
||||
return *PBORDERSIZE;
|
||||
return m_sWindowData.borderSize.valueOr(*PBORDERSIZE);
|
||||
}
|
||||
|
||||
bool CWindow::canBeTorn() {
|
||||
return (m_sAdditionalConfigData.forceTearing.toUnderlying() || m_bTearingHint);
|
||||
}
|
||||
|
||||
bool CWindow::shouldSendFullscreenState() {
|
||||
const auto MODE = m_pWorkspace->m_efFullscreenMode;
|
||||
return m_bDontSendFullscreen ? false : (m_bFakeFullscreenState || (m_bIsFullscreen && (MODE == FULLSCREEN_FULL)));
|
||||
static auto PTEARING = CConfigValue<Hyprlang::INT>("general:allow_tearing");
|
||||
return m_sWindowData.tearing.valueOr(m_bTearingHint) && *PTEARING;
|
||||
}
|
||||
|
||||
void CWindow::setSuspended(bool suspend) {
|
||||
@@ -1229,7 +1199,7 @@ void CWindow::setAnimationsToMove() {
|
||||
|
||||
void CWindow::onWorkspaceAnimUpdate() {
|
||||
// clip box for animated offsets
|
||||
if (!m_bIsFloating || m_bPinned || m_bIsFullscreen) {
|
||||
if (!m_bIsFloating || m_bPinned || isFullscreen()) {
|
||||
m_vFloatingOffset = Vector2D(0, 0);
|
||||
return;
|
||||
}
|
||||
@@ -1283,7 +1253,15 @@ int CWindow::surfacesCount() {
|
||||
return no;
|
||||
}
|
||||
|
||||
int CWindow::workspaceID() {
|
||||
bool CWindow::isFullscreen() {
|
||||
return m_sFullscreenState.internal != FSMODE_NONE;
|
||||
}
|
||||
|
||||
bool CWindow::isEffectiveInternalFSMode(const eFullscreenMode MODE) {
|
||||
return (eFullscreenMode)std::bit_floor((uint8_t)m_sFullscreenState.internal) == MODE;
|
||||
}
|
||||
|
||||
WORKSPACEID CWindow::workspaceID() {
|
||||
return m_pWorkspace ? m_pWorkspace->m_iID : m_iLastWorkspace;
|
||||
}
|
||||
|
||||
@@ -1322,7 +1300,7 @@ std::unordered_map<std::string, std::string> CWindow::getEnv() {
|
||||
|
||||
CVarList envs(std::string{buffer.data(), buffer.size() - 1}, 0, '\n', true);
|
||||
|
||||
for (auto& e : envs) {
|
||||
for (auto const& e : envs) {
|
||||
if (!e.contains('='))
|
||||
continue;
|
||||
|
||||
@@ -1344,10 +1322,14 @@ void CWindow::activate(bool force) {
|
||||
|
||||
m_bIsUrgent = true;
|
||||
|
||||
if (!force &&
|
||||
(!(*PFOCUSONACTIVATE || m_sAdditionalConfigData.focusOnActivate) || (m_eSuppressedEvents & SUPPRESS_ACTIVATE_FOCUSONLY) || (m_eSuppressedEvents & SUPPRESS_ACTIVATE)))
|
||||
if (!force && (!m_sWindowData.focusOnActivate.valueOr(*PFOCUSONACTIVATE) || (m_eSuppressedEvents & SUPPRESS_ACTIVATE_FOCUSONLY) || (m_eSuppressedEvents & SUPPRESS_ACTIVATE)))
|
||||
return;
|
||||
|
||||
if (!m_bIsMapped) {
|
||||
Debug::log(LOG, "Ignoring CWindow::activate focus/warp, window is not mapped yet.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_bIsFloating)
|
||||
g_pCompositor->changeWindowZOrder(m_pSelf.lock(), true);
|
||||
|
||||
@@ -1361,19 +1343,17 @@ void CWindow::onUpdateState() {
|
||||
|
||||
if (requestsFS.has_value() && !(m_eSuppressedEvents & SUPPRESS_FULLSCREEN)) {
|
||||
bool fs = requestsFS.value();
|
||||
|
||||
if (fs != m_bIsFullscreen && m_bIsMapped)
|
||||
g_pCompositor->setWindowFullscreen(m_pSelf.lock(), fs, FULLSCREEN_FULL);
|
||||
if (m_bIsMapped) {
|
||||
g_pCompositor->changeWindowFullscreenModeClient(m_pSelf.lock(), FSMODE_FULLSCREEN, requestsFS.value());
|
||||
}
|
||||
|
||||
if (!m_bIsMapped)
|
||||
m_bWantsInitialFullscreen = fs;
|
||||
}
|
||||
|
||||
if (requestsMX.has_value() && !(m_eSuppressedEvents & SUPPRESS_MAXIMIZE)) {
|
||||
bool fs = requestsMX.value();
|
||||
|
||||
if (fs != m_bIsFullscreen && m_bIsMapped)
|
||||
g_pCompositor->setWindowFullscreen(m_pSelf.lock(), fs, FULLSCREEN_MAXIMIZED);
|
||||
if (m_bIsMapped)
|
||||
g_pCompositor->changeWindowFullscreenModeClient(m_pSelf.lock(), FSMODE_MAXIMIZED, requestsMX.value());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1384,6 +1364,7 @@ void CWindow::onUpdateMeta() {
|
||||
if (m_szTitle != NEWTITLE) {
|
||||
m_szTitle = NEWTITLE;
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"windowtitle", std::format("{:x}", (uintptr_t)this)});
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"windowtitlev2", std::format("{:x},{}", (uintptr_t)this, m_szTitle)});
|
||||
EMIT_HOOK_EVENT("windowTitle", m_pSelf.lock());
|
||||
|
||||
if (m_pSelf == g_pCompositor->m_pLastWindow) { // if it's the active, let's post an event to update others
|
||||
@@ -1477,7 +1458,7 @@ void CWindow::onX11Configure(CBox box) {
|
||||
|
||||
g_pHyprRenderer->damageWindow(m_pSelf.lock());
|
||||
|
||||
if (!m_bIsFloating || m_bIsFullscreen || g_pInputManager->currentlyDraggedWindow == m_pSelf) {
|
||||
if (!m_bIsFloating || isFullscreen() || g_pInputManager->currentlyDraggedWindow == m_pSelf) {
|
||||
g_pXWaylandManager->setWindowSize(m_pSelf.lock(), m_vRealSize.goal(), true);
|
||||
g_pInputManager->refocus();
|
||||
g_pHyprRenderer->damageWindow(m_pSelf.lock());
|
||||
@@ -1521,9 +1502,6 @@ void CWindow::onX11Configure(CBox box) {
|
||||
|
||||
m_bCreatedOverFullscreen = true;
|
||||
|
||||
if (!m_sAdditionalConfigData.windowDanceCompat)
|
||||
g_pInputManager->refocus();
|
||||
|
||||
g_pHyprRenderer->damageWindow(m_pSelf.lock());
|
||||
}
|
||||
|
||||
@@ -1537,3 +1515,75 @@ void CWindow::warpCursor() {
|
||||
else
|
||||
g_pCompositor->warpCursorTo(middle());
|
||||
}
|
||||
|
||||
PHLWINDOW CWindow::getSwallower() {
|
||||
static auto PSWALLOWREGEX = CConfigValue<std::string>("misc:swallow_regex");
|
||||
static auto PSWALLOWEXREGEX = CConfigValue<std::string>("misc:swallow_exception_regex");
|
||||
static auto PSWALLOW = CConfigValue<Hyprlang::INT>("misc:enable_swallow");
|
||||
|
||||
if (!*PSWALLOW || (*PSWALLOWREGEX).empty())
|
||||
return nullptr;
|
||||
|
||||
// check parent
|
||||
std::vector<PHLWINDOW> candidates;
|
||||
pid_t currentPid = getPID();
|
||||
// walk up the tree until we find someone, 25 iterations max.
|
||||
for (size_t i = 0; i < 25; ++i) {
|
||||
currentPid = getPPIDof(currentPid);
|
||||
|
||||
if (!currentPid)
|
||||
break;
|
||||
|
||||
for (auto const& w : g_pCompositor->m_vWindows) {
|
||||
if (!w->m_bIsMapped || w->isHidden())
|
||||
continue;
|
||||
|
||||
if (w->getPID() == currentPid)
|
||||
candidates.push_back(w);
|
||||
}
|
||||
}
|
||||
|
||||
if (!(*PSWALLOWREGEX).empty())
|
||||
std::erase_if(candidates, [&](const auto& other) { return !std::regex_match(other->m_szClass, std::regex(*PSWALLOWREGEX)); });
|
||||
|
||||
if (candidates.size() <= 0)
|
||||
return nullptr;
|
||||
|
||||
if (!(*PSWALLOWEXREGEX).empty())
|
||||
std::erase_if(candidates, [&](const auto& other) { return std::regex_match(other->m_szTitle, std::regex(*PSWALLOWEXREGEX)); });
|
||||
|
||||
if (candidates.size() <= 0)
|
||||
return nullptr;
|
||||
|
||||
if (candidates.size() == 1)
|
||||
return candidates.at(0);
|
||||
|
||||
// walk up the focus history and find the last focused
|
||||
for (auto const& w : g_pCompositor->m_vWindowFocusHistory) {
|
||||
if (!w)
|
||||
continue;
|
||||
|
||||
if (std::find(candidates.begin(), candidates.end(), w.lock()) != candidates.end())
|
||||
return w.lock();
|
||||
}
|
||||
|
||||
// if none are found (??) then just return the first one
|
||||
return candidates.at(0);
|
||||
}
|
||||
|
||||
void CWindow::unsetWindowData(eOverridePriority priority) {
|
||||
for (auto const& element : g_pConfigManager->mbWindowProperties) {
|
||||
element.second(m_pSelf.lock())->unset(priority);
|
||||
}
|
||||
for (auto const& element : g_pConfigManager->miWindowProperties) {
|
||||
element.second(m_pSelf.lock())->unset(priority);
|
||||
}
|
||||
}
|
||||
|
||||
bool CWindow::isX11OverrideRedirect() {
|
||||
return m_pXWaylandSurface && m_pXWaylandSurface->overrideRedirect;
|
||||
}
|
||||
|
||||
bool CWindow::isModal() {
|
||||
return (m_pXWaylandSurface && m_pXWaylandSurface->modal);
|
||||
}
|
||||
|
@@ -6,7 +6,7 @@
|
||||
#include "../config/ConfigDataValues.hpp"
|
||||
#include "../defines.hpp"
|
||||
#include "../helpers/AnimatedVariable.hpp"
|
||||
#include "../helpers/Vector2D.hpp"
|
||||
#include "../helpers/math/Math.hpp"
|
||||
#include "../helpers/signal/Signal.hpp"
|
||||
#include "../helpers/TagKeeper.hpp"
|
||||
#include "../macros.hpp"
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "Popup.hpp"
|
||||
#include "Subsurface.hpp"
|
||||
#include "WLSurface.hpp"
|
||||
#include "Workspace.hpp"
|
||||
|
||||
class CXDGSurfaceResource;
|
||||
class CXWaylandSurface;
|
||||
@@ -59,122 +60,131 @@ enum eSuppressEvents {
|
||||
|
||||
class IWindowTransformer;
|
||||
|
||||
struct SAlphaValue {
|
||||
float m_fAlpha;
|
||||
bool m_bOverride;
|
||||
|
||||
float applyAlpha(float alpha) {
|
||||
if (m_bOverride)
|
||||
return m_fAlpha;
|
||||
else
|
||||
return m_fAlpha * alpha;
|
||||
};
|
||||
};
|
||||
|
||||
enum eOverridePriority {
|
||||
PRIORITY_LAYOUT,
|
||||
PRIORITY_WORKSPACE_RULE,
|
||||
PRIORITY_WINDOW_RULE,
|
||||
PRIORITY_SET_PROP,
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class CWindowOverridableVar {
|
||||
public:
|
||||
CWindowOverridableVar(T val) {
|
||||
value = val;
|
||||
CWindowOverridableVar(T const& value, eOverridePriority priority) {
|
||||
values[priority] = value;
|
||||
}
|
||||
CWindowOverridableVar(T const& value) {
|
||||
defaultValue = value;
|
||||
}
|
||||
|
||||
CWindowOverridableVar() = default;
|
||||
~CWindowOverridableVar() = default;
|
||||
|
||||
CWindowOverridableVar<T>& operator=(CWindowOverridableVar<T> other) {
|
||||
if (locked)
|
||||
CWindowOverridableVar<T>& operator=(CWindowOverridableVar<T> const& other) {
|
||||
// Self-assignment check
|
||||
if (this == &other)
|
||||
return *this;
|
||||
|
||||
locked = other.locked;
|
||||
value = other.value;
|
||||
for (auto const& value : other.values) {
|
||||
values[value.first] = value.second;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
T operator=(T& other) {
|
||||
if (locked)
|
||||
return value;
|
||||
value = other;
|
||||
void unset(eOverridePriority priority) {
|
||||
values.erase(priority);
|
||||
}
|
||||
|
||||
bool hasValue() {
|
||||
return !values.empty();
|
||||
}
|
||||
|
||||
T value() {
|
||||
if (!values.empty())
|
||||
return std::prev(values.end())->second;
|
||||
else
|
||||
throw std::bad_optional_access();
|
||||
}
|
||||
|
||||
T valueOr(T const& other) {
|
||||
if (hasValue())
|
||||
return value();
|
||||
else
|
||||
return other;
|
||||
}
|
||||
|
||||
void forceSetIgnoreLocked(T val, bool lock = false) {
|
||||
value = val;
|
||||
locked = lock;
|
||||
T valueOrDefault() {
|
||||
return valueOr(defaultValue);
|
||||
}
|
||||
|
||||
T operator*(T& other) {
|
||||
return value * other;
|
||||
eOverridePriority getPriority() {
|
||||
if (!values.empty())
|
||||
return std::prev(values.end())->first;
|
||||
else
|
||||
throw std::bad_optional_access();
|
||||
}
|
||||
|
||||
T operator+(T& other) {
|
||||
return value + other;
|
||||
void matchOptional(std::optional<T> const& optValue, eOverridePriority priority) {
|
||||
if (optValue.has_value())
|
||||
values[priority] = optValue.value();
|
||||
else
|
||||
unset(priority);
|
||||
}
|
||||
|
||||
bool operator==(T& other) {
|
||||
return other == value;
|
||||
}
|
||||
|
||||
bool operator>=(T& other) {
|
||||
return value >= other;
|
||||
}
|
||||
|
||||
bool operator<=(T& other) {
|
||||
return value <= other;
|
||||
}
|
||||
|
||||
bool operator>(T& other) {
|
||||
return value > other;
|
||||
}
|
||||
|
||||
bool operator<(T& other) {
|
||||
return value < other;
|
||||
}
|
||||
|
||||
explicit operator bool() {
|
||||
return static_cast<bool>(value);
|
||||
}
|
||||
|
||||
T toUnderlying() {
|
||||
return value;
|
||||
}
|
||||
|
||||
bool locked = false;
|
||||
|
||||
private:
|
||||
T value;
|
||||
std::map<eOverridePriority, T> values;
|
||||
T defaultValue; // used for toggling, so required for bool
|
||||
};
|
||||
|
||||
struct SWindowSpecialRenderData {
|
||||
CWindowOverridableVar<bool> alphaOverride = false;
|
||||
CWindowOverridableVar<float> alpha = 1.f;
|
||||
CWindowOverridableVar<bool> alphaInactiveOverride = false;
|
||||
CWindowOverridableVar<float> alphaInactive = -1.f; // -1 means unset
|
||||
CWindowOverridableVar<bool> alphaFullscreenOverride = false;
|
||||
CWindowOverridableVar<float> alphaFullscreen = -1.f; // -1 means unset
|
||||
struct SWindowData {
|
||||
CWindowOverridableVar<SAlphaValue> alpha = SAlphaValue{1.f, false};
|
||||
CWindowOverridableVar<SAlphaValue> alphaInactive = SAlphaValue{1.f, false};
|
||||
CWindowOverridableVar<SAlphaValue> alphaFullscreen = SAlphaValue{1.f, false};
|
||||
|
||||
CWindowOverridableVar<CGradientValueData> activeBorderColor = CGradientValueData(); // empty color vector means unset
|
||||
CWindowOverridableVar<CGradientValueData> inactiveBorderColor = CGradientValueData(); // empty color vector means unset
|
||||
|
||||
// set by the layout
|
||||
CWindowOverridableVar<int> borderSize = -1; // -1 means unset
|
||||
bool rounding = true;
|
||||
bool border = true;
|
||||
bool decorate = true;
|
||||
bool shadow = true;
|
||||
};
|
||||
|
||||
struct SWindowAdditionalConfigData {
|
||||
std::string animationStyle = std::string("");
|
||||
CWindowOverridableVar<int> rounding = -1; // -1 means no
|
||||
CWindowOverridableVar<bool> forceNoBlur = false;
|
||||
CWindowOverridableVar<bool> forceOpaque = false;
|
||||
CWindowOverridableVar<bool> forceOpaqueOverridden = false; // if true, a rule will not change the forceOpaque state. This is for the force opaque dispatcher.
|
||||
CWindowOverridableVar<bool> forceAllowsInput = false;
|
||||
CWindowOverridableVar<bool> forceNoAnims = false;
|
||||
CWindowOverridableVar<bool> forceNoBorder = false;
|
||||
CWindowOverridableVar<bool> forceNoShadow = false;
|
||||
CWindowOverridableVar<bool> forceNoDim = false;
|
||||
CWindowOverridableVar<bool> noFocus = false;
|
||||
CWindowOverridableVar<bool> windowDanceCompat = false;
|
||||
CWindowOverridableVar<bool> noMaxSize = false;
|
||||
CWindowOverridableVar<Vector2D> maxSize = Vector2D(std::numeric_limits<double>::max(), std::numeric_limits<double>::max());
|
||||
CWindowOverridableVar<Vector2D> minSize = Vector2D(20, 20);
|
||||
CWindowOverridableVar<bool> allowsInput = false;
|
||||
CWindowOverridableVar<bool> dimAround = false;
|
||||
CWindowOverridableVar<bool> forceRGBX = false;
|
||||
CWindowOverridableVar<bool> keepAspectRatio = false;
|
||||
CWindowOverridableVar<bool> decorate = true;
|
||||
CWindowOverridableVar<bool> focusOnActivate = false;
|
||||
CWindowOverridableVar<int> xray = -1; // -1 means unset, takes precedence over the renderdata one
|
||||
CWindowOverridableVar<int> borderSize = -1; // -1 means unset, takes precedence over the renderdata one
|
||||
CWindowOverridableVar<bool> forceTearing = false;
|
||||
CWindowOverridableVar<bool> keepAspectRatio = false;
|
||||
CWindowOverridableVar<bool> nearestNeighbor = false;
|
||||
CWindowOverridableVar<bool> noAnim = false;
|
||||
CWindowOverridableVar<bool> noBorder = false;
|
||||
CWindowOverridableVar<bool> noBlur = false;
|
||||
CWindowOverridableVar<bool> noDim = false;
|
||||
CWindowOverridableVar<bool> noFocus = false;
|
||||
CWindowOverridableVar<bool> noMaxSize = false;
|
||||
CWindowOverridableVar<bool> noRounding = false;
|
||||
CWindowOverridableVar<bool> noShadow = false;
|
||||
CWindowOverridableVar<bool> noShortcutsInhibit = false;
|
||||
CWindowOverridableVar<bool> opaque = false;
|
||||
CWindowOverridableVar<bool> RGBX = false;
|
||||
CWindowOverridableVar<bool> syncFullscreen = true;
|
||||
CWindowOverridableVar<bool> tearing = false;
|
||||
CWindowOverridableVar<bool> xray = false;
|
||||
CWindowOverridableVar<bool> renderUnfocused = false;
|
||||
|
||||
CWindowOverridableVar<int> rounding;
|
||||
CWindowOverridableVar<int> borderSize;
|
||||
|
||||
CWindowOverridableVar<std::string> animationStyle;
|
||||
CWindowOverridableVar<Vector2D> maxSize;
|
||||
CWindowOverridableVar<Vector2D> minSize;
|
||||
|
||||
CWindowOverridableVar<CGradientValueData> activeBorderColor;
|
||||
CWindowOverridableVar<CGradientValueData> inactiveBorderColor;
|
||||
};
|
||||
|
||||
struct SWindowRule {
|
||||
@@ -192,6 +202,7 @@ struct SWindowRule {
|
||||
int bFullscreen = -1;
|
||||
int bPinned = -1;
|
||||
int bFocus = -1;
|
||||
std::string szFullscreenState = ""; // empty means any
|
||||
std::string szOnWorkspace = ""; // empty means any
|
||||
std::string szWorkspace = ""; // empty means any
|
||||
};
|
||||
@@ -201,6 +212,11 @@ struct SInitialWorkspaceToken {
|
||||
std::string workspace;
|
||||
};
|
||||
|
||||
struct sFullscreenState {
|
||||
eFullscreenMode internal = FSMODE_NONE;
|
||||
eFullscreenMode client = FSMODE_NONE;
|
||||
};
|
||||
|
||||
class CWindow {
|
||||
public:
|
||||
static PHLWINDOW create(SP<CXDGSurfaceResource>);
|
||||
@@ -254,10 +270,9 @@ class CWindow {
|
||||
bool m_bFirstMap = false; // for layouts
|
||||
bool m_bIsFloating = false;
|
||||
bool m_bDraggingTiled = false; // for dragging around tiled windows
|
||||
bool m_bIsFullscreen = false;
|
||||
bool m_bDontSendFullscreen = false;
|
||||
bool m_bWasMaximized = false;
|
||||
uint64_t m_iMonitorID = -1;
|
||||
sFullscreenState m_sFullscreenState = {.internal = FSMODE_NONE, .client = FSMODE_NONE};
|
||||
MONITORID m_iMonitorID = -1;
|
||||
std::string m_szTitle = "";
|
||||
std::string m_szClass = "";
|
||||
std::string m_szInitialTitle = "";
|
||||
@@ -274,8 +289,6 @@ class CWindow {
|
||||
// XWayland stuff
|
||||
bool m_bIsX11 = false;
|
||||
PHLWINDOWREF m_pX11Parent;
|
||||
uint64_t m_iX11Type = 0;
|
||||
bool m_bIsModal = false;
|
||||
bool m_bX11DoesntWantBorders = false;
|
||||
bool m_bX11ShouldntFocus = false;
|
||||
float m_fX11SurfaceScaledBy = 1.f;
|
||||
@@ -306,7 +319,7 @@ class CWindow {
|
||||
bool m_bReadyToDelete = false;
|
||||
Vector2D m_vOriginalClosedPos; // these will be used for calculations later on in
|
||||
Vector2D m_vOriginalClosedSize; // drawing the closing animations
|
||||
SWindowDecorationExtents m_eOriginalClosedExtents;
|
||||
SBoxExtents m_eOriginalClosedExtents;
|
||||
bool m_bAnimatingIn = false;
|
||||
|
||||
// For pinned (sticky) windows
|
||||
@@ -315,9 +328,6 @@ class CWindow {
|
||||
// urgency hint
|
||||
bool m_bIsUrgent = false;
|
||||
|
||||
// fakefullscreen
|
||||
bool m_bFakeFullscreenState = false;
|
||||
|
||||
// for proper cycling. While cycling we can't just move the pointers, so we need to keep track of the last cycled window.
|
||||
PHLWINDOWREF m_pLastCycledWindow;
|
||||
|
||||
@@ -327,8 +337,7 @@ class CWindow {
|
||||
std::vector<IHyprWindowDecoration*> m_vDecosToRemove;
|
||||
|
||||
// Special render data, rules, etc
|
||||
SWindowSpecialRenderData m_sSpecialRenderData;
|
||||
SWindowAdditionalConfigData m_sAdditionalConfigData;
|
||||
SWindowData m_sWindowData;
|
||||
|
||||
// Transformers
|
||||
std::vector<std::unique_ptr<IWindowTransformer>> m_vTransformers;
|
||||
@@ -342,6 +351,10 @@ class CWindow {
|
||||
// animated tint
|
||||
CAnimatedVariable<float> m_fDimPercent;
|
||||
|
||||
// animate moving to an invisible workspace
|
||||
int m_iMonitorMovedFrom = -1; // -1 means not moving
|
||||
CAnimatedVariable<float> m_fMovingToWorkspaceAlpha;
|
||||
|
||||
// swallowing
|
||||
PHLWINDOWREF m_pSwallowed;
|
||||
|
||||
@@ -349,8 +362,8 @@ class CWindow {
|
||||
bool m_bStayFocused = false;
|
||||
|
||||
// for toplevel monitor events
|
||||
uint64_t m_iLastToplevelMonitorID = -1;
|
||||
uint64_t m_iLastSurfaceMonitorID = -1;
|
||||
MONITORID m_iLastToplevelMonitorID = -1;
|
||||
MONITORID m_iLastSurfaceMonitorID = -1;
|
||||
|
||||
// for idle inhibiting windows
|
||||
eIdleInhibitMode m_eIdleInhibitMode = IDLEINHIBIT_NONE;
|
||||
@@ -383,7 +396,7 @@ class CWindow {
|
||||
|
||||
// methods
|
||||
CBox getFullWindowBoundingBox();
|
||||
SWindowDecorationExtents getFullWindowExtents();
|
||||
SBoxExtents getFullWindowExtents();
|
||||
CBox getWindowBoxUnified(uint64_t props);
|
||||
CBox getWindowMainSurfaceBox();
|
||||
CBox getWindowIdealBoundingBoxIgnoreReserved();
|
||||
@@ -405,22 +418,24 @@ class CWindow {
|
||||
bool isHidden();
|
||||
void applyDynamicRule(const SWindowRule& r);
|
||||
void updateDynamicRules();
|
||||
SWindowDecorationExtents getFullWindowReservedArea();
|
||||
SBoxExtents getFullWindowReservedArea();
|
||||
Vector2D middle();
|
||||
bool opaque();
|
||||
float rounding();
|
||||
bool canBeTorn();
|
||||
bool shouldSendFullscreenState();
|
||||
void setSuspended(bool suspend);
|
||||
bool visibleOnMonitor(CMonitor* pMonitor);
|
||||
int workspaceID();
|
||||
WORKSPACEID workspaceID();
|
||||
bool onSpecialWorkspace();
|
||||
void activate(bool force = false);
|
||||
int surfacesCount();
|
||||
|
||||
bool isFullscreen();
|
||||
bool isEffectiveInternalFSMode(const eFullscreenMode);
|
||||
|
||||
int getRealBorderSize();
|
||||
void updateSpecialRenderData();
|
||||
void updateSpecialRenderData(const struct SWorkspaceRule&);
|
||||
void updateWindowData();
|
||||
void updateWindowData(const struct SWorkspaceRule&);
|
||||
|
||||
void onBorderAngleAnimEnd(void* ptr);
|
||||
bool isInCurvedCorner(double x, double y);
|
||||
@@ -450,6 +465,10 @@ class CWindow {
|
||||
std::string fetchTitle();
|
||||
std::string fetchClass();
|
||||
void warpCursor();
|
||||
PHLWINDOW getSwallower();
|
||||
void unsetWindowData(eOverridePriority priority);
|
||||
bool isX11OverrideRedirect();
|
||||
bool isModal();
|
||||
|
||||
// listeners
|
||||
void onAck(uint32_t serial);
|
||||
@@ -479,7 +498,7 @@ class CWindow {
|
||||
// For hidden windows and stuff
|
||||
bool m_bHidden = false;
|
||||
bool m_bSuspended = false;
|
||||
int m_iLastWorkspace = WORKSPACE_INVALID;
|
||||
WORKSPACEID m_iLastWorkspace = WORKSPACE_INVALID;
|
||||
};
|
||||
|
||||
inline bool valid(PHLWINDOW w) {
|
||||
|
@@ -2,27 +2,31 @@
|
||||
#include "../Compositor.hpp"
|
||||
#include "../config/ConfigValue.hpp"
|
||||
|
||||
PHLWORKSPACE CWorkspace::create(int id, int monitorID, std::string name, bool special, bool isEmtpy) {
|
||||
PHLWORKSPACE workspace = makeShared<CWorkspace>(id, monitorID, name, special, isEmtpy);
|
||||
#include <hyprutils/string/String.hpp>
|
||||
using namespace Hyprutils::String;
|
||||
|
||||
PHLWORKSPACE CWorkspace::create(WORKSPACEID id, MONITORID monitorID, std::string name, bool special, bool isEmpty) {
|
||||
PHLWORKSPACE workspace = makeShared<CWorkspace>(id, monitorID, name, special, isEmpty);
|
||||
workspace->init(workspace);
|
||||
return workspace;
|
||||
}
|
||||
|
||||
CWorkspace::CWorkspace(int id, int monitorID, std::string name, bool special, bool isEmtpy) {
|
||||
CWorkspace::CWorkspace(WORKSPACEID id, MONITORID monitorID, std::string name, bool special, bool isEmpty) {
|
||||
m_iMonitorID = monitorID;
|
||||
m_iID = id;
|
||||
m_szName = name;
|
||||
m_bIsSpecialWorkspace = special;
|
||||
m_bWasCreatedEmtpy = isEmtpy;
|
||||
m_bWasCreatedEmpty = isEmpty;
|
||||
}
|
||||
|
||||
void CWorkspace::init(PHLWORKSPACE self) {
|
||||
m_pSelf = self;
|
||||
|
||||
m_vRenderOffset.create(m_bIsSpecialWorkspace ? g_pConfigManager->getAnimationPropertyConfig("specialWorkspace") : g_pConfigManager->getAnimationPropertyConfig("workspaces"),
|
||||
m_vRenderOffset.create(m_bIsSpecialWorkspace ? g_pConfigManager->getAnimationPropertyConfig("specialWorkspaceIn") :
|
||||
g_pConfigManager->getAnimationPropertyConfig("workspacesIn"),
|
||||
self, AVARDAMAGE_ENTIRE);
|
||||
m_fAlpha.create(AVARTYPE_FLOAT,
|
||||
m_bIsSpecialWorkspace ? g_pConfigManager->getAnimationPropertyConfig("specialWorkspace") : g_pConfigManager->getAnimationPropertyConfig("workspaces"), self,
|
||||
m_bIsSpecialWorkspace ? g_pConfigManager->getAnimationPropertyConfig("specialWorkspaceIn") : g_pConfigManager->getAnimationPropertyConfig("workspacesIn"), self,
|
||||
AVARDAMAGE_ENTIRE);
|
||||
m_fAlpha.setValueAndWarp(1.f);
|
||||
|
||||
@@ -45,15 +49,22 @@ void CWorkspace::init(PHLWORKSPACE self) {
|
||||
const auto WORKSPACERULE = g_pConfigManager->getWorkspaceRuleFor(self);
|
||||
m_bPersistent = WORKSPACERULE.isPersistent;
|
||||
|
||||
if (self->m_bWasCreatedEmtpy)
|
||||
if (self->m_bWasCreatedEmpty)
|
||||
if (auto cmd = WORKSPACERULE.onCreatedEmptyRunCmd)
|
||||
g_pKeybindManager->spawn(*cmd);
|
||||
g_pKeybindManager->spawnWithRules(*cmd, self);
|
||||
|
||||
g_pEventManager->postEvent({"createworkspace", m_szName});
|
||||
g_pEventManager->postEvent({"createworkspacev2", std::format("{},{}", m_iID, m_szName)});
|
||||
EMIT_HOOK_EVENT("createWorkspace", this);
|
||||
}
|
||||
|
||||
SWorkspaceIDName CWorkspace::getPrevWorkspaceIDName(bool perMonitor) const {
|
||||
if (perMonitor)
|
||||
return m_sPrevWorkspacePerMonitor;
|
||||
|
||||
return m_sPrevWorkspace;
|
||||
}
|
||||
|
||||
CWorkspace::~CWorkspace() {
|
||||
m_vRenderOffset.unregister();
|
||||
|
||||
@@ -71,12 +82,19 @@ CWorkspace::~CWorkspace() {
|
||||
}
|
||||
|
||||
void CWorkspace::startAnim(bool in, bool left, bool instant) {
|
||||
if (!instant) {
|
||||
const std::string ANIMNAME = std::format("{}{}", m_bIsSpecialWorkspace ? "specialWorkspace" : "workspaces", in ? "In" : "Out");
|
||||
|
||||
m_fAlpha.m_pConfig = g_pConfigManager->getAnimationPropertyConfig(ANIMNAME);
|
||||
m_vRenderOffset.m_pConfig = g_pConfigManager->getAnimationPropertyConfig(ANIMNAME);
|
||||
}
|
||||
|
||||
const auto ANIMSTYLE = m_fAlpha.m_pConfig->pValues->internalStyle;
|
||||
static auto PWORKSPACEGAP = CConfigValue<Hyprlang::INT>("general:gaps_workspaces");
|
||||
|
||||
// set floating windows offset callbacks
|
||||
m_vRenderOffset.setUpdateCallback([&](void*) {
|
||||
for (auto& w : g_pCompositor->m_vWindows) {
|
||||
for (auto const& w : g_pCompositor->m_vWindows) {
|
||||
if (!validMapped(w) || w->workspaceID() != m_iID)
|
||||
continue;
|
||||
|
||||
@@ -101,24 +119,24 @@ void CWorkspace::startAnim(bool in, bool left, bool instant) {
|
||||
if (ANIMSTYLE.starts_with("slidefadevert")) {
|
||||
if (in) {
|
||||
m_fAlpha.setValueAndWarp(0.f);
|
||||
m_vRenderOffset.setValueAndWarp(Vector2D(0, (left ? PMONITOR->vecSize.y : -PMONITOR->vecSize.y) * (movePerc / 100.f)));
|
||||
m_vRenderOffset.setValueAndWarp(Vector2D(0.0, (left ? PMONITOR->vecSize.y : -PMONITOR->vecSize.y) * (movePerc / 100.f)));
|
||||
m_fAlpha = 1.f;
|
||||
m_vRenderOffset = Vector2D(0, 0);
|
||||
} else {
|
||||
m_fAlpha.setValueAndWarp(1.f);
|
||||
m_fAlpha = 0.f;
|
||||
m_vRenderOffset = Vector2D(0, (left ? -PMONITOR->vecSize.y : PMONITOR->vecSize.y) * (movePerc / 100.f));
|
||||
m_vRenderOffset = Vector2D(0.0, (left ? -PMONITOR->vecSize.y : PMONITOR->vecSize.y) * (movePerc / 100.f));
|
||||
}
|
||||
} else {
|
||||
if (in) {
|
||||
m_fAlpha.setValueAndWarp(0.f);
|
||||
m_vRenderOffset.setValueAndWarp(Vector2D((left ? PMONITOR->vecSize.x : -PMONITOR->vecSize.x) * (movePerc / 100.f), 0));
|
||||
m_vRenderOffset.setValueAndWarp(Vector2D((left ? PMONITOR->vecSize.x : -PMONITOR->vecSize.x) * (movePerc / 100.f), 0.0));
|
||||
m_fAlpha = 1.f;
|
||||
m_vRenderOffset = Vector2D(0, 0);
|
||||
} else {
|
||||
m_fAlpha.setValueAndWarp(1.f);
|
||||
m_fAlpha = 0.f;
|
||||
m_vRenderOffset = Vector2D((left ? -PMONITOR->vecSize.x : PMONITOR->vecSize.x) * (movePerc / 100.f), 0);
|
||||
m_vRenderOffset = Vector2D((left ? -PMONITOR->vecSize.x : PMONITOR->vecSize.x) * (movePerc / 100.f), 0.0);
|
||||
}
|
||||
}
|
||||
} else if (ANIMSTYLE == "fade") {
|
||||
@@ -139,10 +157,10 @@ void CWorkspace::startAnim(bool in, bool left, bool instant) {
|
||||
m_fAlpha.setValueAndWarp(1.f); // fix a bug, if switching from fade -> slide.
|
||||
|
||||
if (in) {
|
||||
m_vRenderOffset.setValueAndWarp(Vector2D(0, left ? YDISTANCE : -YDISTANCE));
|
||||
m_vRenderOffset.setValueAndWarp(Vector2D(0.0, left ? YDISTANCE : -YDISTANCE));
|
||||
m_vRenderOffset = Vector2D(0, 0);
|
||||
} else {
|
||||
m_vRenderOffset = Vector2D(0, left ? -YDISTANCE : YDISTANCE);
|
||||
m_vRenderOffset = Vector2D(0.0, left ? -YDISTANCE : YDISTANCE);
|
||||
}
|
||||
} else {
|
||||
// fallback is slide
|
||||
@@ -152,10 +170,10 @@ void CWorkspace::startAnim(bool in, bool left, bool instant) {
|
||||
m_fAlpha.setValueAndWarp(1.f); // fix a bug, if switching from fade -> slide.
|
||||
|
||||
if (in) {
|
||||
m_vRenderOffset.setValueAndWarp(Vector2D(left ? XDISTANCE : -XDISTANCE, 0));
|
||||
m_vRenderOffset.setValueAndWarp(Vector2D(left ? XDISTANCE : -XDISTANCE, 0.0));
|
||||
m_vRenderOffset = Vector2D(0, 0);
|
||||
} else {
|
||||
m_vRenderOffset = Vector2D(left ? -XDISTANCE : XDISTANCE, 0);
|
||||
m_vRenderOffset = Vector2D(left ? -XDISTANCE : XDISTANCE, 0.0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -180,7 +198,7 @@ void CWorkspace::setActive(bool on) {
|
||||
; // empty until https://gitlab.freedesktop.org/wayland/wayland-protocols/-/merge_requests/40
|
||||
}
|
||||
|
||||
void CWorkspace::moveToMonitor(const int& id) {
|
||||
void CWorkspace::moveToMonitor(const MONITORID& id) {
|
||||
; // empty until https://gitlab.freedesktop.org/wayland/wayland-protocols/-/merge_requests/40
|
||||
}
|
||||
|
||||
@@ -193,7 +211,7 @@ PHLWINDOW CWorkspace::getLastFocusedWindow() {
|
||||
|
||||
void CWorkspace::rememberPrevWorkspace(const PHLWORKSPACE& prev) {
|
||||
if (!prev) {
|
||||
m_sPrevWorkspace.iID = -1;
|
||||
m_sPrevWorkspace.id = -1;
|
||||
m_sPrevWorkspace.name = "";
|
||||
return;
|
||||
}
|
||||
@@ -203,8 +221,13 @@ void CWorkspace::rememberPrevWorkspace(const PHLWORKSPACE& prev) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_sPrevWorkspace.iID = prev->m_iID;
|
||||
m_sPrevWorkspace.id = prev->m_iID;
|
||||
m_sPrevWorkspace.name = prev->m_szName;
|
||||
|
||||
if (prev->m_iMonitorID == m_iMonitorID) {
|
||||
m_sPrevWorkspacePerMonitor.id = prev->m_iID;
|
||||
m_sPrevWorkspacePerMonitor.name = prev->m_szName;
|
||||
}
|
||||
}
|
||||
|
||||
std::string CWorkspace::getConfigName() {
|
||||
@@ -219,15 +242,13 @@ std::string CWorkspace::getConfigName() {
|
||||
}
|
||||
|
||||
bool CWorkspace::matchesStaticSelector(const std::string& selector_) {
|
||||
auto selector = removeBeginEndSpacesTabs(selector_);
|
||||
auto selector = trim(selector_);
|
||||
|
||||
if (selector.empty())
|
||||
return true;
|
||||
|
||||
if (isNumber(selector)) {
|
||||
|
||||
std::string wsname = "";
|
||||
int wsid = getWorkspaceIDFromString(selector, wsname);
|
||||
const auto& [wsid, wsname] = getWorkspaceIDNameFromString(selector);
|
||||
|
||||
if (wsid == WORKSPACE_INVALID)
|
||||
return false;
|
||||
@@ -262,7 +283,7 @@ bool CWorkspace::matchesStaticSelector(const std::string& selector_) {
|
||||
i = std::min(NEXTSPACE, std::string::npos - 1);
|
||||
|
||||
if (cur == 'r') {
|
||||
int from = 0, to = 0;
|
||||
WORKSPACEID from = 0, to = 0;
|
||||
if (!prop.starts_with("r[") || !prop.ends_with("]")) {
|
||||
Debug::log(LOG, "Invalid selector {}", selector);
|
||||
return false;
|
||||
@@ -352,7 +373,7 @@ bool CWorkspace::matchesStaticSelector(const std::string& selector_) {
|
||||
}
|
||||
|
||||
if (cur == 'w') {
|
||||
int from = 0, to = 0;
|
||||
WORKSPACEID from = 0, to = 0;
|
||||
if (!prop.starts_with("w[") || !prop.ends_with("]")) {
|
||||
Debug::log(LOG, "Invalid selector {}", selector);
|
||||
return false;
|
||||
@@ -365,7 +386,7 @@ bool CWorkspace::matchesStaticSelector(const std::string& selector_) {
|
||||
bool wantsCountVisible = false;
|
||||
|
||||
int flagCount = 0;
|
||||
for (auto& flag : prop) {
|
||||
for (auto const& flag : prop) {
|
||||
if (flag == 't' && wantsOnlyTiled == -1) {
|
||||
wantsOnlyTiled = 1;
|
||||
flagCount++;
|
||||
@@ -433,7 +454,7 @@ bool CWorkspace::matchesStaticSelector(const std::string& selector_) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int count;
|
||||
WORKSPACEID count;
|
||||
if (wantsCountGroup)
|
||||
count = g_pCompositor->getGroupsOnWorkspace(m_iID, wantsOnlyTiled == -1 ? std::nullopt : std::optional<bool>((bool)wantsOnlyTiled),
|
||||
wantsCountVisible ? std::optional<bool>(wantsCountVisible) : std::nullopt);
|
||||
@@ -467,16 +488,11 @@ bool CWorkspace::matchesStaticSelector(const std::string& selector_) {
|
||||
return false;
|
||||
break;
|
||||
case 0: // fullscreen full
|
||||
if (!m_bHasFullscreenWindow || m_efFullscreenMode != FULLSCREEN_FULL)
|
||||
if (!m_bHasFullscreenWindow || m_efFullscreenMode != FSMODE_FULLSCREEN)
|
||||
return false;
|
||||
break;
|
||||
case 1: // maximized
|
||||
if (!m_bHasFullscreenWindow || m_efFullscreenMode != FULLSCREEN_MAXIMIZED)
|
||||
return false;
|
||||
break;
|
||||
case 2: // fullscreen without sending fullscreen state to window
|
||||
if (!m_bHasFullscreenWindow || m_efFullscreenMode != FULLSCREEN_FULL || !g_pCompositor->getFullscreenWindowOnWorkspace(m_iID) ||
|
||||
!g_pCompositor->getFullscreenWindowOnWorkspace(m_iID)->m_bDontSendFullscreen)
|
||||
if (!m_bHasFullscreenWindow || m_efFullscreenMode != FSMODE_MAXIMIZED)
|
||||
return false;
|
||||
break;
|
||||
default: break;
|
||||
@@ -498,7 +514,7 @@ bool CWorkspace::matchesStaticSelector(const std::string& selector_) {
|
||||
void CWorkspace::markInert() {
|
||||
m_bInert = true;
|
||||
m_iID = WORKSPACE_INVALID;
|
||||
m_iMonitorID = -1;
|
||||
m_iMonitorID = MONITOR_INVALID;
|
||||
m_bVisible = false;
|
||||
}
|
||||
|
||||
|
@@ -4,36 +4,35 @@
|
||||
#include <string>
|
||||
#include "../defines.hpp"
|
||||
#include "DesktopTypes.hpp"
|
||||
#include "../helpers/MiscFunctions.hpp"
|
||||
|
||||
enum eFullscreenMode : int8_t {
|
||||
FULLSCREEN_INVALID = -1,
|
||||
FULLSCREEN_FULL = 0,
|
||||
FULLSCREEN_MAXIMIZED
|
||||
FSMODE_NONE = 0,
|
||||
FSMODE_MAXIMIZED = 1 << 0,
|
||||
FSMODE_FULLSCREEN = 1 << 1,
|
||||
FSMODE_MAX = (1 << 2) - 1
|
||||
};
|
||||
|
||||
class CWindow;
|
||||
|
||||
class CWorkspace {
|
||||
public:
|
||||
static PHLWORKSPACE create(int id, int monitorID, std::string name, bool special = false, bool isEmtpy = true);
|
||||
static PHLWORKSPACE create(WORKSPACEID id, MONITORID monitorID, std::string name, bool special = false, bool isEmpty = true);
|
||||
// use create() don't use this
|
||||
CWorkspace(int id, int monitorID, std::string name, bool special = false, bool isEmpty = true);
|
||||
CWorkspace(WORKSPACEID id, MONITORID monitorID, std::string name, bool special = false, bool isEmpty = true);
|
||||
~CWorkspace();
|
||||
|
||||
// Workspaces ID-based have IDs > 0
|
||||
// and workspaces name-based have IDs starting with -1337
|
||||
int m_iID = -1;
|
||||
WORKSPACEID m_iID = WORKSPACE_INVALID;
|
||||
std::string m_szName = "";
|
||||
uint64_t m_iMonitorID = -1;
|
||||
// Previous workspace ID is stored during a workspace change, allowing travel
|
||||
MONITORID m_iMonitorID = MONITOR_INVALID;
|
||||
// Previous workspace ID and name is stored during a workspace change, allowing travel
|
||||
// to the previous workspace.
|
||||
struct SPrevWorkspaceData {
|
||||
int iID = -1;
|
||||
std::string name = "";
|
||||
} m_sPrevWorkspace;
|
||||
SWorkspaceIDName m_sPrevWorkspace, m_sPrevWorkspacePerMonitor;
|
||||
|
||||
bool m_bHasFullscreenWindow = false;
|
||||
eFullscreenMode m_efFullscreenMode = FULLSCREEN_FULL;
|
||||
eFullscreenMode m_efFullscreenMode = FSMODE_NONE;
|
||||
|
||||
wl_array m_wlrCoordinateArr;
|
||||
|
||||
@@ -58,7 +57,7 @@ class CWorkspace {
|
||||
// last monitor (used on reconnect)
|
||||
std::string m_szLastMonitor = "";
|
||||
|
||||
bool m_bWasCreatedEmtpy = true;
|
||||
bool m_bWasCreatedEmpty = true;
|
||||
|
||||
bool m_bPersistent = false;
|
||||
|
||||
@@ -68,7 +67,7 @@ class CWorkspace {
|
||||
void startAnim(bool in, bool left, bool instant = false);
|
||||
void setActive(bool on);
|
||||
|
||||
void moveToMonitor(const int&);
|
||||
void moveToMonitor(const MONITORID&);
|
||||
|
||||
PHLWINDOW getLastFocusedWindow();
|
||||
void rememberPrevWorkspace(const PHLWORKSPACE& prevWorkspace);
|
||||
@@ -79,6 +78,8 @@ class CWorkspace {
|
||||
|
||||
void markInert();
|
||||
|
||||
SWorkspaceIDName getPrevWorkspaceIDName(bool perMonitor) const;
|
||||
|
||||
private:
|
||||
void init(PHLWORKSPACE self);
|
||||
|
||||
|
@@ -1,8 +1,22 @@
|
||||
#include "IKeyboard.hpp"
|
||||
#include "../defines.hpp"
|
||||
#include "../helpers/VarList.hpp"
|
||||
#include "../helpers/varlist/VarList.hpp"
|
||||
#include "../managers/input/InputManager.hpp"
|
||||
#include "../managers/SeatManager.hpp"
|
||||
#include "../config/ConfigManager.hpp"
|
||||
#include <sys/mman.h>
|
||||
#include <aquamarine/input/Input.hpp>
|
||||
#include <cstring>
|
||||
|
||||
#define LED_COUNT 3
|
||||
|
||||
constexpr static std::array<const char*, 8> MODNAMES = {
|
||||
XKB_MOD_NAME_SHIFT, XKB_MOD_NAME_CAPS, XKB_MOD_NAME_CTRL, XKB_MOD_NAME_ALT, XKB_MOD_NAME_NUM, "Mod3", XKB_MOD_NAME_LOGO, "Mod5",
|
||||
};
|
||||
|
||||
constexpr static std::array<const char*, 3> LEDNAMES = {XKB_LED_NAME_NUM, XKB_LED_NAME_CAPS, XKB_LED_NAME_SCROLL};
|
||||
|
||||
//
|
||||
uint32_t IKeyboard::getCapabilities() {
|
||||
return HID_INPUT_CAPABILITY_KEYBOARD;
|
||||
}
|
||||
@@ -14,27 +28,173 @@ eHIDType IKeyboard::getType() {
|
||||
IKeyboard::~IKeyboard() {
|
||||
events.destroy.emit();
|
||||
|
||||
if (!xkbTranslationState)
|
||||
return;
|
||||
clearManuallyAllocd();
|
||||
}
|
||||
|
||||
xkb_state_unref(xkbTranslationState);
|
||||
xkbTranslationState = nullptr;
|
||||
void IKeyboard::clearManuallyAllocd() {
|
||||
if (xkbStaticState)
|
||||
xkb_state_unref(xkbStaticState);
|
||||
|
||||
if (xkbState)
|
||||
xkb_state_unref(xkbState);
|
||||
|
||||
if (xkbKeymap)
|
||||
xkb_keymap_unref(xkbKeymap);
|
||||
|
||||
if (xkbKeymapFD >= 0)
|
||||
close(xkbKeymapFD);
|
||||
|
||||
xkbKeymap = nullptr;
|
||||
xkbState = nullptr;
|
||||
xkbStaticState = nullptr;
|
||||
xkbKeymapFD = -1;
|
||||
}
|
||||
|
||||
void IKeyboard::setKeymap(const SStringRuleNames& rules) {
|
||||
if (keymapOverridden) {
|
||||
Debug::log(LOG, "Ignoring setKeymap: keymap is overridden");
|
||||
return;
|
||||
}
|
||||
|
||||
currentRules = rules;
|
||||
xkb_rule_names XKBRULES = {
|
||||
.rules = rules.rules.c_str(),
|
||||
.model = rules.model.c_str(),
|
||||
.layout = rules.layout.c_str(),
|
||||
.variant = rules.variant.c_str(),
|
||||
.options = rules.options.c_str(),
|
||||
};
|
||||
|
||||
const auto CONTEXT = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
|
||||
|
||||
if (!CONTEXT) {
|
||||
Debug::log(ERR, "setKeymap: CONTEXT null??");
|
||||
return;
|
||||
}
|
||||
|
||||
clearManuallyAllocd();
|
||||
|
||||
Debug::log(LOG, "Attempting to create a keymap for layout {} with variant {} (rules: {}, model: {}, options: {})", rules.layout, rules.variant, rules.rules, rules.model,
|
||||
rules.options);
|
||||
|
||||
if (!xkbFilePath.empty()) {
|
||||
auto path = absolutePath(xkbFilePath, g_pConfigManager->configCurrentPath);
|
||||
|
||||
if (FILE* const KEYMAPFILE = fopen(path.c_str(), "r"); !KEYMAPFILE)
|
||||
Debug::log(ERR, "Cannot open input:kb_file= file for reading");
|
||||
else {
|
||||
xkbKeymap = xkb_keymap_new_from_file(CONTEXT, KEYMAPFILE, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS);
|
||||
fclose(KEYMAPFILE);
|
||||
}
|
||||
}
|
||||
|
||||
if (!xkbKeymap)
|
||||
xkbKeymap = xkb_keymap_new_from_names(CONTEXT, &XKBRULES, XKB_KEYMAP_COMPILE_NO_FLAGS);
|
||||
|
||||
if (!xkbKeymap) {
|
||||
g_pConfigManager->addParseError("Invalid keyboard layout passed. ( rules: " + rules.rules + ", model: " + rules.model + ", variant: " + rules.variant +
|
||||
", options: " + rules.options + ", layout: " + rules.layout + " )");
|
||||
|
||||
Debug::log(ERR, "Keyboard layout {} with variant {} (rules: {}, model: {}, options: {}) couldn't have been loaded.", rules.layout, rules.variant, rules.rules, rules.model,
|
||||
rules.options);
|
||||
memset(&XKBRULES, 0, sizeof(XKBRULES));
|
||||
|
||||
currentRules.rules = "";
|
||||
currentRules.model = "";
|
||||
currentRules.variant = "";
|
||||
currentRules.options = "";
|
||||
currentRules.layout = "us";
|
||||
|
||||
xkbKeymap = xkb_keymap_new_from_names(CONTEXT, &XKBRULES, XKB_KEYMAP_COMPILE_NO_FLAGS);
|
||||
}
|
||||
|
||||
updateXKBTranslationState(xkbKeymap);
|
||||
|
||||
const auto NUMLOCKON = g_pConfigManager->getDeviceInt(hlName, "numlock_by_default", "input:numlock_by_default");
|
||||
|
||||
if (NUMLOCKON == 1) {
|
||||
// lock numlock
|
||||
const auto IDX = xkb_map_mod_get_index(xkbKeymap, XKB_MOD_NAME_NUM);
|
||||
|
||||
if (IDX != XKB_MOD_INVALID)
|
||||
modifiersState.locked |= (uint32_t)1 << IDX;
|
||||
|
||||
// 0 to avoid mods getting stuck if depressed during reload
|
||||
updateModifiers(0, 0, modifiersState.locked, modifiersState.group);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < LEDNAMES.size(); ++i) {
|
||||
ledIndexes.at(i) = xkb_map_led_get_index(xkbKeymap, LEDNAMES.at(i));
|
||||
Debug::log(LOG, "xkb: LED index {} (name {}) got index {}", i, LEDNAMES.at(i), ledIndexes.at(i));
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < MODNAMES.size(); ++i) {
|
||||
modIndexes.at(i) = xkb_map_mod_get_index(xkbKeymap, MODNAMES.at(i));
|
||||
Debug::log(LOG, "xkb: Mod index {} (name {}) got index {}", i, MODNAMES.at(i), modIndexes.at(i));
|
||||
}
|
||||
|
||||
updateKeymapFD();
|
||||
|
||||
xkb_context_unref(CONTEXT);
|
||||
|
||||
g_pSeatManager->updateActiveKeyboardData();
|
||||
}
|
||||
|
||||
void IKeyboard::updateKeymapFD() {
|
||||
Debug::log(LOG, "Updating keymap fd for keyboard {}", deviceName);
|
||||
|
||||
if (xkbKeymapFD >= 0)
|
||||
close(xkbKeymapFD);
|
||||
xkbKeymapFD = -1;
|
||||
|
||||
auto cKeymapStr = xkb_keymap_get_as_string(xkbKeymap, XKB_KEYMAP_FORMAT_TEXT_V1);
|
||||
xkbKeymapString = cKeymapStr;
|
||||
free(cKeymapStr);
|
||||
|
||||
int rw, ro;
|
||||
if (!allocateSHMFilePair(xkbKeymapString.length() + 1, &rw, &ro))
|
||||
Debug::log(ERR, "IKeyboard: failed to allocate shm pair for the keymap");
|
||||
else {
|
||||
auto keymapFDDest = mmap(nullptr, xkbKeymapString.length() + 1, PROT_READ | PROT_WRITE, MAP_SHARED, rw, 0);
|
||||
close(rw);
|
||||
if (keymapFDDest == MAP_FAILED) {
|
||||
Debug::log(ERR, "IKeyboard: failed to mmap a shm pair for the keymap");
|
||||
close(ro);
|
||||
} else {
|
||||
memcpy(keymapFDDest, xkbKeymapString.c_str(), xkbKeymapString.length());
|
||||
munmap(keymapFDDest, xkbKeymapString.length() + 1);
|
||||
xkbKeymapFD = ro;
|
||||
}
|
||||
}
|
||||
|
||||
Debug::log(LOG, "Updated keymap fd to {}", xkbKeymapFD);
|
||||
}
|
||||
|
||||
void IKeyboard::updateXKBTranslationState(xkb_keymap* const keymap) {
|
||||
|
||||
if (xkbTranslationState)
|
||||
xkb_state_unref(xkbTranslationState);
|
||||
if (xkbStaticState)
|
||||
xkb_state_unref(xkbStaticState);
|
||||
|
||||
if (xkbState)
|
||||
xkb_state_unref(xkbState);
|
||||
|
||||
if (xkbSymState)
|
||||
xkb_state_unref(xkbSymState);
|
||||
|
||||
xkbState = nullptr;
|
||||
xkbStaticState = nullptr;
|
||||
xkbSymState = nullptr;
|
||||
|
||||
if (keymap) {
|
||||
Debug::log(LOG, "Updating keyboard {:x}'s translation state from a provided keymap", (uintptr_t)this);
|
||||
xkbTranslationState = xkb_state_new(keymap);
|
||||
xkbStaticState = xkb_state_new(keymap);
|
||||
xkbState = xkb_state_new(keymap);
|
||||
xkbSymState = xkb_state_new(keymap);
|
||||
return;
|
||||
}
|
||||
|
||||
const auto WLRKB = wlr();
|
||||
const auto KEYMAP = WLRKB->keymap;
|
||||
const auto STATE = WLRKB->xkb_state;
|
||||
const auto KEYMAP = xkbKeymap;
|
||||
const auto STATE = xkbState;
|
||||
const auto LAYOUTSNUM = xkb_keymap_num_layouts(KEYMAP);
|
||||
|
||||
const auto PCONTEXT = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
|
||||
@@ -73,7 +233,9 @@ void IKeyboard::updateXKBTranslationState(xkb_keymap* const keymap) {
|
||||
KEYMAP = xkb_keymap_new_from_names(PCONTEXT, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS);
|
||||
}
|
||||
|
||||
xkbTranslationState = xkb_state_new(KEYMAP);
|
||||
xkbState = xkb_state_new(KEYMAP);
|
||||
xkbStaticState = xkb_state_new(KEYMAP);
|
||||
xkbSymState = xkb_state_new(KEYMAP);
|
||||
|
||||
xkb_keymap_unref(KEYMAP);
|
||||
xkb_context_unref(PCONTEXT);
|
||||
@@ -94,16 +256,17 @@ void IKeyboard::updateXKBTranslationState(xkb_keymap* const keymap) {
|
||||
|
||||
const auto NEWKEYMAP = xkb_keymap_new_from_names(PCONTEXT, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS);
|
||||
|
||||
xkbTranslationState = xkb_state_new(NEWKEYMAP);
|
||||
xkbState = xkb_state_new(NEWKEYMAP);
|
||||
xkbStaticState = xkb_state_new(NEWKEYMAP);
|
||||
xkbSymState = xkb_state_new(NEWKEYMAP);
|
||||
|
||||
xkb_keymap_unref(NEWKEYMAP);
|
||||
xkb_context_unref(PCONTEXT);
|
||||
}
|
||||
|
||||
std::string IKeyboard::getActiveLayout() {
|
||||
const auto WLRKB = wlr();
|
||||
const auto KEYMAP = WLRKB->keymap;
|
||||
const auto STATE = WLRKB->xkb_state;
|
||||
const auto KEYMAP = xkbKeymap;
|
||||
const auto STATE = xkbState;
|
||||
const auto LAYOUTSNUM = xkb_keymap_num_layouts(KEYMAP);
|
||||
|
||||
for (uint32_t i = 0; i < LAYOUTSNUM; ++i) {
|
||||
@@ -119,29 +282,124 @@ std::string IKeyboard::getActiveLayout() {
|
||||
return "none";
|
||||
}
|
||||
|
||||
void IKeyboard::updateLEDs() {
|
||||
auto keyboard = wlr();
|
||||
|
||||
if (!keyboard || keyboard->xkb_state == nullptr)
|
||||
return;
|
||||
std::optional<uint32_t> IKeyboard::getLEDs() {
|
||||
if (xkbState == nullptr)
|
||||
return {};
|
||||
|
||||
uint32_t leds = 0;
|
||||
for (uint32_t i = 0; i < WLR_LED_COUNT; ++i) {
|
||||
if (xkb_state_led_index_is_active(keyboard->xkb_state, keyboard->led_indexes[i]))
|
||||
for (uint32_t i = 0; i < LED_COUNT; ++i) {
|
||||
if (xkb_state_led_index_is_active(xkbState, ledIndexes.at(i)))
|
||||
leds |= (1 << i);
|
||||
}
|
||||
|
||||
updateLEDs(leds);
|
||||
return leds;
|
||||
}
|
||||
|
||||
void IKeyboard::updateLEDs() {
|
||||
std::optional<uint32_t> leds = getLEDs();
|
||||
|
||||
if (!leds.has_value())
|
||||
return;
|
||||
|
||||
updateLEDs(leds.value());
|
||||
}
|
||||
|
||||
void IKeyboard::updateLEDs(uint32_t leds) {
|
||||
auto keyboard = wlr();
|
||||
|
||||
if (!keyboard || keyboard->xkb_state == nullptr)
|
||||
if (!xkbState)
|
||||
return;
|
||||
|
||||
if (isVirtual() && g_pInputManager->shouldIgnoreVirtualKeyboard(self.lock()))
|
||||
return;
|
||||
|
||||
wlr_keyboard_led_update(keyboard, leds);
|
||||
if (!aq())
|
||||
return;
|
||||
|
||||
aq()->updateLEDs(leds);
|
||||
}
|
||||
|
||||
uint32_t IKeyboard::getModifiers() {
|
||||
uint32_t modMask = modifiersState.depressed | modifiersState.latched;
|
||||
uint32_t mods = 0;
|
||||
for (size_t i = 0; i < modIndexes.size(); ++i) {
|
||||
if (modIndexes.at(i) == XKB_MOD_INVALID)
|
||||
continue;
|
||||
|
||||
if (!(modMask & (1 << modIndexes.at(i))))
|
||||
continue;
|
||||
|
||||
mods |= (1 << i);
|
||||
}
|
||||
|
||||
return mods;
|
||||
}
|
||||
|
||||
void IKeyboard::updateModifiers(uint32_t depressed, uint32_t latched, uint32_t locked, uint32_t group) {
|
||||
if (!xkbState)
|
||||
return;
|
||||
|
||||
xkb_state_update_mask(xkbState, depressed, latched, locked, 0, 0, group);
|
||||
|
||||
if (xkbSymState)
|
||||
xkb_state_update_mask(xkbSymState, 0, 0, 0, 0, 0, group);
|
||||
|
||||
if (!updateModifiersState())
|
||||
return;
|
||||
|
||||
keyboardEvents.modifiers.emit(SModifiersEvent{
|
||||
.depressed = modifiersState.depressed,
|
||||
.latched = modifiersState.latched,
|
||||
.locked = modifiersState.locked,
|
||||
.group = modifiersState.group,
|
||||
});
|
||||
|
||||
updateLEDs();
|
||||
}
|
||||
|
||||
bool IKeyboard::updateModifiersState() {
|
||||
if (!xkbState)
|
||||
return false;
|
||||
|
||||
auto depressed = xkb_state_serialize_mods(xkbState, XKB_STATE_MODS_DEPRESSED);
|
||||
auto latched = xkb_state_serialize_mods(xkbState, XKB_STATE_MODS_LATCHED);
|
||||
auto locked = xkb_state_serialize_mods(xkbState, XKB_STATE_MODS_LOCKED);
|
||||
auto group = xkb_state_serialize_layout(xkbState, XKB_STATE_LAYOUT_EFFECTIVE);
|
||||
|
||||
if (depressed == modifiersState.depressed && latched == modifiersState.latched && locked == modifiersState.locked && group == modifiersState.group)
|
||||
return false;
|
||||
|
||||
modifiersState.depressed = depressed;
|
||||
modifiersState.latched = latched;
|
||||
modifiersState.locked = locked;
|
||||
modifiersState.group = group;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void IKeyboard::updateXkbStateWithKey(uint32_t xkbKey, bool pressed) {
|
||||
|
||||
const auto contains = std::find(pressedXKB.begin(), pressedXKB.end(), xkbKey) != pressedXKB.end();
|
||||
|
||||
if (contains && pressed)
|
||||
return;
|
||||
if (!contains && !pressed)
|
||||
return;
|
||||
|
||||
if (contains)
|
||||
std::erase(pressedXKB, xkbKey);
|
||||
else
|
||||
pressedXKB.emplace_back(xkbKey);
|
||||
|
||||
xkb_state_update_key(xkbState, xkbKey, pressed ? XKB_KEY_DOWN : XKB_KEY_UP);
|
||||
|
||||
if (updateModifiersState()) {
|
||||
if (xkbSymState)
|
||||
xkb_state_update_mask(xkbSymState, 0, 0, 0, 0, 0, modifiersState.group);
|
||||
|
||||
keyboardEvents.modifiers.emit(SModifiersEvent{
|
||||
.depressed = modifiersState.depressed,
|
||||
.latched = modifiersState.latched,
|
||||
.locked = modifiersState.locked,
|
||||
.group = modifiersState.group,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@@ -1,13 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include "IHID.hpp"
|
||||
#include "../helpers/WLListener.hpp"
|
||||
#include "../macros.hpp"
|
||||
#include "../helpers/Vector2D.hpp"
|
||||
#include "../helpers/math/Math.hpp"
|
||||
|
||||
#include <optional>
|
||||
#include <xkbcommon/xkbcommon.h>
|
||||
|
||||
struct wlr_keyboard;
|
||||
AQUAMARINE_FORWARD(IKeyboard);
|
||||
|
||||
enum eKeyboardModifiers {
|
||||
HL_MODIFIER_SHIFT = (1 << 0),
|
||||
HL_MODIFIER_CAPS = (1 << 1),
|
||||
HL_MODIFIER_CTRL = (1 << 2),
|
||||
HL_MODIFIER_ALT = (1 << 3),
|
||||
HL_MODIFIER_MOD2 = (1 << 4),
|
||||
HL_MODIFIER_MOD3 = (1 << 5),
|
||||
HL_MODIFIER_META = (1 << 6),
|
||||
HL_MODIFIER_MOD5 = (1 << 7),
|
||||
};
|
||||
|
||||
class IKeyboard : public IHID {
|
||||
public:
|
||||
@@ -15,7 +26,7 @@ class IKeyboard : public IHID {
|
||||
virtual uint32_t getCapabilities();
|
||||
virtual eHIDType getType();
|
||||
virtual bool isVirtual() = 0;
|
||||
virtual wlr_keyboard* wlr() = 0;
|
||||
virtual SP<Aquamarine::IKeyboard> aq() = 0;
|
||||
|
||||
struct SKeyEvent {
|
||||
uint32_t timeMs = 0;
|
||||
@@ -24,6 +35,17 @@ class IKeyboard : public IHID {
|
||||
wl_keyboard_key_state state = WL_KEYBOARD_KEY_STATE_PRESSED;
|
||||
};
|
||||
|
||||
struct SKeymapEvent {
|
||||
xkb_keymap* keymap = nullptr;
|
||||
};
|
||||
|
||||
struct SModifiersEvent {
|
||||
uint32_t depressed = 0;
|
||||
uint32_t latched = 0;
|
||||
uint32_t locked = 0;
|
||||
uint32_t group = 0;
|
||||
};
|
||||
|
||||
struct {
|
||||
CSignal key;
|
||||
CSignal modifiers;
|
||||
@@ -39,19 +61,43 @@ class IKeyboard : public IHID {
|
||||
std::string rules = "";
|
||||
};
|
||||
|
||||
void setKeymap(const SStringRuleNames& rules);
|
||||
void updateXKBTranslationState(xkb_keymap* const keymap = nullptr);
|
||||
std::string getActiveLayout();
|
||||
std::optional<uint32_t> getLEDs();
|
||||
void updateLEDs();
|
||||
void updateLEDs(uint32_t leds);
|
||||
uint32_t getModifiers();
|
||||
void updateModifiers(uint32_t depressed, uint32_t latched, uint32_t locked, uint32_t group);
|
||||
bool updateModifiersState(); // rets whether changed
|
||||
void updateXkbStateWithKey(uint32_t xkbKey, bool pressed);
|
||||
void updateKeymapFD();
|
||||
|
||||
bool active = false;
|
||||
bool enabled = true;
|
||||
|
||||
// if the keymap is overridden by the implementation,
|
||||
// don't try to set keyboard rules anymore, to avoid overwriting the requested one.
|
||||
// e.g. Virtual keyboards with custom maps.
|
||||
bool keymapOverridden = false;
|
||||
|
||||
xkb_layout_index_t activeLayout = 0;
|
||||
xkb_state* xkbTranslationState = nullptr;
|
||||
xkb_state * xkbState = nullptr, *xkbStaticState /* Static state: never gets modifiers or layout changes sent, used for keybinds. */ = nullptr,
|
||||
*xkbSymState = nullptr /* Same as static but gets layouts */;
|
||||
xkb_keymap* xkbKeymap = nullptr;
|
||||
|
||||
struct {
|
||||
uint32_t depressed = 0, latched = 0, locked = 0, group = 0;
|
||||
} modifiersState;
|
||||
|
||||
std::array<xkb_led_index_t, 3> ledIndexes = {XKB_MOD_INVALID};
|
||||
std::array<xkb_mod_index_t, 8> modIndexes = {XKB_MOD_INVALID};
|
||||
uint32_t leds = 0;
|
||||
|
||||
std::string hlName = "";
|
||||
std::string xkbFilePath = "";
|
||||
std::string xkbKeymapString = "";
|
||||
int xkbKeymapFD = -1;
|
||||
|
||||
SStringRuleNames currentRules;
|
||||
int repeatRate = 0;
|
||||
@@ -60,4 +106,9 @@ class IKeyboard : public IHID {
|
||||
bool resolveBindsBySym = false;
|
||||
|
||||
WP<IKeyboard> self;
|
||||
|
||||
private:
|
||||
void clearManuallyAllocd();
|
||||
|
||||
std::vector<uint32_t> pressedXKB;
|
||||
};
|
||||
|
@@ -1,11 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include "IHID.hpp"
|
||||
#include "../helpers/WLListener.hpp"
|
||||
#include "../macros.hpp"
|
||||
#include "../helpers/Vector2D.hpp"
|
||||
#include "../helpers/math/Math.hpp"
|
||||
|
||||
struct wlr_pointer;
|
||||
AQUAMARINE_FORWARD(IPointer);
|
||||
|
||||
/*
|
||||
Base class for a pointer.
|
||||
@@ -15,7 +14,7 @@ class IPointer : public IHID {
|
||||
virtual uint32_t getCapabilities();
|
||||
virtual eHIDType getType();
|
||||
virtual bool isVirtual() = 0;
|
||||
virtual wlr_pointer* wlr() = 0;
|
||||
virtual SP<Aquamarine::IPointer> aq() = 0;
|
||||
|
||||
struct SMotionEvent {
|
||||
uint32_t timeMs = 0;
|
||||
@@ -107,6 +106,7 @@ class IPointer : public IHID {
|
||||
|
||||
std::string hlName;
|
||||
bool connected = false; // means connected to the cursor
|
||||
std::string boundOutput = "";
|
||||
|
||||
WP<IPointer> self;
|
||||
};
|
||||
|
@@ -1,18 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#include "IHID.hpp"
|
||||
#include "../helpers/WLListener.hpp"
|
||||
#include "../macros.hpp"
|
||||
#include "../helpers/Vector2D.hpp"
|
||||
#include "../helpers/math/Math.hpp"
|
||||
|
||||
struct wlr_touch;
|
||||
AQUAMARINE_FORWARD(ITouch);
|
||||
|
||||
class ITouch : public IHID {
|
||||
public:
|
||||
virtual uint32_t getCapabilities();
|
||||
virtual eHIDType getType();
|
||||
virtual bool isVirtual() = 0;
|
||||
virtual wlr_touch* wlr() = 0;
|
||||
virtual SP<Aquamarine::ITouch> aq() = 0;
|
||||
|
||||
struct SDownEvent {
|
||||
uint32_t timeMs = 0;
|
||||
|
@@ -1,7 +1,10 @@
|
||||
#include "Keyboard.hpp"
|
||||
#include "../defines.hpp"
|
||||
#include "../Compositor.hpp"
|
||||
|
||||
SP<CKeyboard> CKeyboard::create(wlr_keyboard* keeb) {
|
||||
#include <aquamarine/input/Input.hpp>
|
||||
|
||||
SP<CKeyboard> CKeyboard::create(SP<Aquamarine::IKeyboard> keeb) {
|
||||
SP<CKeyboard> pKeeb = SP<CKeyboard>(new CKeyboard(keeb));
|
||||
|
||||
pKeeb->self = pKeeb;
|
||||
@@ -13,52 +16,41 @@ bool CKeyboard::isVirtual() {
|
||||
return false;
|
||||
}
|
||||
|
||||
wlr_keyboard* CKeyboard::wlr() {
|
||||
return keyboard;
|
||||
SP<Aquamarine::IKeyboard> CKeyboard::aq() {
|
||||
return keyboard.lock();
|
||||
}
|
||||
|
||||
CKeyboard::CKeyboard(wlr_keyboard* keeb) : keyboard(keeb) {
|
||||
CKeyboard::CKeyboard(SP<Aquamarine::IKeyboard> keeb) : keyboard(keeb) {
|
||||
if (!keeb)
|
||||
return;
|
||||
|
||||
// clang-format off
|
||||
hyprListener_destroy.initCallback(&keeb->base.events.destroy, [this] (void* owner, void* data) {
|
||||
disconnectCallbacks();
|
||||
keyboard = nullptr;
|
||||
listeners.destroy = keeb->events.destroy.registerListener([this](std::any d) {
|
||||
keyboard.reset();
|
||||
events.destroy.emit();
|
||||
}, this, "CKeyboard");
|
||||
});
|
||||
|
||||
hyprListener_key.initCallback(&keeb->events.key, [this] (void* owner, void* data) {
|
||||
auto E = (wlr_keyboard_key_event*)data;
|
||||
listeners.key = keeb->events.key.registerListener([this](std::any d) {
|
||||
auto E = std::any_cast<Aquamarine::IKeyboard::SKeyEvent>(d);
|
||||
|
||||
keyboardEvents.key.emit(SKeyEvent{
|
||||
.timeMs = E->time_msec,
|
||||
.keycode = E->keycode,
|
||||
.updateMods = E->update_state,
|
||||
.state = E->state,
|
||||
.timeMs = E.timeMs,
|
||||
.keycode = E.key,
|
||||
.state = E.pressed ? WL_KEYBOARD_KEY_STATE_PRESSED : WL_KEYBOARD_KEY_STATE_RELEASED,
|
||||
});
|
||||
}, this, "CKeyboard");
|
||||
|
||||
hyprListener_keymap.initCallback(&keeb->events.keymap, [this] (void* owner, void* data) {
|
||||
keyboardEvents.keymap.emit();
|
||||
}, this, "CKeyboard");
|
||||
updateXkbStateWithKey(E.key + 8, E.pressed);
|
||||
});
|
||||
|
||||
hyprListener_modifiers.initCallback(&keeb->events.modifiers, [this] (void* owner, void* data) {
|
||||
keyboardEvents.modifiers.emit();
|
||||
}, this, "CKeyboard");
|
||||
listeners.modifiers = keeb->events.modifiers.registerListener([this](std::any d) {
|
||||
updateModifiersState();
|
||||
|
||||
hyprListener_repeatInfo.initCallback(&keeb->events.repeat_info, [this] (void* owner, void* data) {
|
||||
keyboardEvents.repeatInfo.emit();
|
||||
}, this, "CKeyboard");
|
||||
// clang-format on
|
||||
keyboardEvents.modifiers.emit(SModifiersEvent{
|
||||
.depressed = modifiersState.depressed,
|
||||
.latched = modifiersState.latched,
|
||||
.locked = modifiersState.locked,
|
||||
.group = modifiersState.group,
|
||||
});
|
||||
});
|
||||
|
||||
deviceName = keeb->base.name ? keeb->base.name : "UNKNOWN";
|
||||
}
|
||||
|
||||
void CKeyboard::disconnectCallbacks() {
|
||||
hyprListener_destroy.removeCallback();
|
||||
hyprListener_key.removeCallback();
|
||||
hyprListener_keymap.removeCallback();
|
||||
hyprListener_repeatInfo.removeCallback();
|
||||
hyprListener_modifiers.removeCallback();
|
||||
deviceName = keeb->getName();
|
||||
}
|
||||
|
@@ -4,21 +4,19 @@
|
||||
|
||||
class CKeyboard : public IKeyboard {
|
||||
public:
|
||||
static SP<CKeyboard> create(wlr_keyboard* keeb);
|
||||
static SP<CKeyboard> create(SP<Aquamarine::IKeyboard> keeb);
|
||||
|
||||
virtual bool isVirtual();
|
||||
virtual wlr_keyboard* wlr();
|
||||
virtual SP<Aquamarine::IKeyboard> aq();
|
||||
|
||||
private:
|
||||
CKeyboard(wlr_keyboard* keeb);
|
||||
CKeyboard(SP<Aquamarine::IKeyboard> keeb);
|
||||
|
||||
wlr_keyboard* keyboard = nullptr;
|
||||
WP<Aquamarine::IKeyboard> keyboard;
|
||||
|
||||
void disconnectCallbacks();
|
||||
|
||||
DYNLISTENER(destroy);
|
||||
DYNLISTENER(key);
|
||||
DYNLISTENER(modifiers);
|
||||
DYNLISTENER(keymap);
|
||||
DYNLISTENER(repeatInfo);
|
||||
struct {
|
||||
CHyprSignalListener destroy;
|
||||
CHyprSignalListener key;
|
||||
CHyprSignalListener modifiers;
|
||||
} listeners;
|
||||
};
|
@@ -1,7 +1,8 @@
|
||||
#include "Mouse.hpp"
|
||||
#include "../defines.hpp"
|
||||
#include <aquamarine/input/Input.hpp>
|
||||
|
||||
SP<CMouse> CMouse::create(wlr_pointer* mouse) {
|
||||
SP<CMouse> CMouse::create(SP<Aquamarine::IPointer> mouse) {
|
||||
SP<CMouse> pMouse = SP<CMouse>(new CMouse(mouse));
|
||||
|
||||
pMouse->self = pMouse;
|
||||
@@ -9,166 +10,143 @@ SP<CMouse> CMouse::create(wlr_pointer* mouse) {
|
||||
return pMouse;
|
||||
}
|
||||
|
||||
CMouse::CMouse(wlr_pointer* mouse_) : mouse(mouse_) {
|
||||
CMouse::CMouse(SP<Aquamarine::IPointer> mouse_) : mouse(mouse_) {
|
||||
if (!mouse)
|
||||
return;
|
||||
|
||||
// clang-format off
|
||||
hyprListener_destroy.initCallback(&mouse->base.events.destroy, [this] (void* owner, void* data) {
|
||||
disconnectCallbacks();
|
||||
mouse = nullptr;
|
||||
listeners.destroy = mouse->events.destroy.registerListener([this](std::any d) {
|
||||
mouse.reset();
|
||||
events.destroy.emit();
|
||||
}, this, "CMouse");
|
||||
});
|
||||
|
||||
hyprListener_motion.initCallback(&mouse->events.motion, [this] (void* owner, void* data) {
|
||||
auto E = (wlr_pointer_motion_event*)data;
|
||||
listeners.motion = mouse->events.move.registerListener([this](std::any d) {
|
||||
auto E = std::any_cast<Aquamarine::IPointer::SMoveEvent>(d);
|
||||
|
||||
pointerEvents.motion.emit(SMotionEvent{
|
||||
.timeMs = E->time_msec,
|
||||
.delta = {E->delta_x, E->delta_y},
|
||||
.unaccel = {E->unaccel_dx, E->unaccel_dy},
|
||||
.timeMs = E.timeMs,
|
||||
.delta = E.delta,
|
||||
.unaccel = E.unaccel,
|
||||
});
|
||||
});
|
||||
}, this, "CMouse");
|
||||
|
||||
hyprListener_motionAbsolute.initCallback(&mouse->events.motion_absolute, [this] (void* owner, void* data) {
|
||||
auto E = (wlr_pointer_motion_absolute_event*)data;
|
||||
listeners.motionAbsolute = mouse->events.warp.registerListener([this](std::any d) {
|
||||
auto E = std::any_cast<Aquamarine::IPointer::SWarpEvent>(d);
|
||||
|
||||
pointerEvents.motionAbsolute.emit(SMotionAbsoluteEvent{
|
||||
.timeMs = E->time_msec,
|
||||
.absolute = {E->x, E->y},
|
||||
.timeMs = E.timeMs,
|
||||
.absolute = E.absolute,
|
||||
.device = self.lock(),
|
||||
});
|
||||
}, this, "CMouse");
|
||||
});
|
||||
|
||||
hyprListener_button.initCallback(&mouse->events.button, [this] (void* owner, void* data) {
|
||||
auto E = (wlr_pointer_button_event*)data;
|
||||
listeners.button = mouse->events.button.registerListener([this](std::any d) {
|
||||
auto E = std::any_cast<Aquamarine::IPointer::SButtonEvent>(d);
|
||||
|
||||
pointerEvents.button.emit(SButtonEvent{
|
||||
.timeMs = E->time_msec,
|
||||
.button = E->button,
|
||||
.state = (wl_pointer_button_state)E->state,
|
||||
.timeMs = E.timeMs,
|
||||
.button = E.button,
|
||||
.state = E.pressed ? WL_POINTER_BUTTON_STATE_PRESSED : WL_POINTER_BUTTON_STATE_RELEASED,
|
||||
});
|
||||
});
|
||||
}, this, "CMouse");
|
||||
|
||||
hyprListener_axis.initCallback(&mouse->events.axis, [this] (void* owner, void* data) {
|
||||
auto E = (wlr_pointer_axis_event*)data;
|
||||
listeners.axis = mouse->events.axis.registerListener([this](std::any d) {
|
||||
auto E = std::any_cast<Aquamarine::IPointer::SAxisEvent>(d);
|
||||
|
||||
pointerEvents.axis.emit(SAxisEvent{
|
||||
.timeMs = E->time_msec,
|
||||
.source = E->source,
|
||||
.axis = E->orientation,
|
||||
.relativeDirection = E->relative_direction,
|
||||
.delta = E->delta,
|
||||
.deltaDiscrete = E->delta_discrete,
|
||||
.timeMs = E.timeMs,
|
||||
.source = (wl_pointer_axis_source)E.source,
|
||||
.axis = (wl_pointer_axis)E.axis,
|
||||
.relativeDirection = (wl_pointer_axis_relative_direction)E.direction,
|
||||
.delta = E.delta,
|
||||
.deltaDiscrete = E.discrete,
|
||||
});
|
||||
});
|
||||
}, this, "CMouse");
|
||||
|
||||
hyprListener_frame.initCallback(&mouse->events.frame, [this] (void* owner, void* data) {
|
||||
pointerEvents.frame.emit();
|
||||
}, this, "CMouse");
|
||||
listeners.frame = mouse->events.frame.registerListener([this](std::any d) { pointerEvents.frame.emit(); });
|
||||
|
||||
hyprListener_swipeBegin.initCallback(&mouse->events.swipe_begin, [this] (void* owner, void* data) {
|
||||
auto E = (wlr_pointer_swipe_begin_event*)data;
|
||||
listeners.swipeBegin = mouse->events.swipeBegin.registerListener([this](std::any d) {
|
||||
auto E = std::any_cast<Aquamarine::IPointer::SSwipeBeginEvent>(d);
|
||||
|
||||
pointerEvents.swipeBegin.emit(SSwipeBeginEvent{
|
||||
.timeMs = E->time_msec,
|
||||
.fingers = E->fingers,
|
||||
.timeMs = E.timeMs,
|
||||
.fingers = E.fingers,
|
||||
});
|
||||
});
|
||||
}, this, "CMouse");
|
||||
|
||||
hyprListener_swipeEnd.initCallback(&mouse->events.swipe_end, [this] (void* owner, void* data) {
|
||||
auto E = (wlr_pointer_swipe_end_event*)data;
|
||||
listeners.swipeEnd = mouse->events.swipeEnd.registerListener([this](std::any d) {
|
||||
auto E = std::any_cast<Aquamarine::IPointer::SSwipeEndEvent>(d);
|
||||
|
||||
pointerEvents.swipeEnd.emit(SSwipeEndEvent{
|
||||
.timeMs = E->time_msec,
|
||||
.cancelled = E->cancelled,
|
||||
.timeMs = E.timeMs,
|
||||
.cancelled = E.cancelled,
|
||||
});
|
||||
});
|
||||
}, this, "CMouse");
|
||||
|
||||
hyprListener_swipeUpdate.initCallback(&mouse->events.swipe_update, [this] (void* owner, void* data) {
|
||||
auto E = (wlr_pointer_swipe_update_event*)data;
|
||||
listeners.swipeUpdate = mouse->events.swipeUpdate.registerListener([this](std::any d) {
|
||||
auto E = std::any_cast<Aquamarine::IPointer::SSwipeUpdateEvent>(d);
|
||||
|
||||
pointerEvents.swipeUpdate.emit(SSwipeUpdateEvent{
|
||||
.timeMs = E->time_msec,
|
||||
.fingers = E->fingers,
|
||||
.delta = {E->dx, E->dy},
|
||||
.timeMs = E.timeMs,
|
||||
.fingers = E.fingers,
|
||||
.delta = E.delta,
|
||||
});
|
||||
});
|
||||
}, this, "CMouse");
|
||||
|
||||
hyprListener_pinchBegin.initCallback(&mouse->events.pinch_begin, [this] (void* owner, void* data) {
|
||||
auto E = (wlr_pointer_pinch_begin_event*)data;
|
||||
listeners.pinchBegin = mouse->events.pinchBegin.registerListener([this](std::any d) {
|
||||
auto E = std::any_cast<Aquamarine::IPointer::SPinchBeginEvent>(d);
|
||||
|
||||
pointerEvents.pinchBegin.emit(SPinchBeginEvent{
|
||||
.timeMs = E->time_msec,
|
||||
.fingers = E->fingers,
|
||||
.timeMs = E.timeMs,
|
||||
.fingers = E.fingers,
|
||||
});
|
||||
});
|
||||
}, this, "CMouse");
|
||||
|
||||
hyprListener_pinchEnd.initCallback(&mouse->events.pinch_end, [this] (void* owner, void* data) {
|
||||
auto E = (wlr_pointer_pinch_end_event*)data;
|
||||
listeners.pinchEnd = mouse->events.pinchEnd.registerListener([this](std::any d) {
|
||||
auto E = std::any_cast<Aquamarine::IPointer::SPinchEndEvent>(d);
|
||||
|
||||
pointerEvents.pinchEnd.emit(SPinchEndEvent{
|
||||
.timeMs = E->time_msec,
|
||||
.cancelled = E->cancelled,
|
||||
.timeMs = E.timeMs,
|
||||
.cancelled = E.cancelled,
|
||||
});
|
||||
});
|
||||
}, this, "CMouse");
|
||||
|
||||
hyprListener_pinchUpdate.initCallback(&mouse->events.pinch_update, [this] (void* owner, void* data) {
|
||||
auto E = (wlr_pointer_pinch_update_event*)data;
|
||||
listeners.pinchUpdate = mouse->events.pinchUpdate.registerListener([this](std::any d) {
|
||||
auto E = std::any_cast<Aquamarine::IPointer::SPinchUpdateEvent>(d);
|
||||
|
||||
pointerEvents.pinchUpdate.emit(SPinchUpdateEvent{
|
||||
.timeMs = E->time_msec,
|
||||
.fingers = E->fingers,
|
||||
.delta = {E->dx, E->dy},
|
||||
.scale = E->scale,
|
||||
.rotation = E->rotation,
|
||||
.timeMs = E.timeMs,
|
||||
.fingers = E.fingers,
|
||||
.delta = E.delta,
|
||||
.scale = E.scale,
|
||||
.rotation = E.rotation,
|
||||
});
|
||||
});
|
||||
}, this, "CMouse");
|
||||
|
||||
hyprListener_holdBegin.initCallback(&mouse->events.hold_begin, [this] (void* owner, void* data) {
|
||||
auto E = (wlr_pointer_hold_begin_event*)data;
|
||||
listeners.holdBegin = mouse->events.holdBegin.registerListener([this](std::any d) {
|
||||
auto E = std::any_cast<Aquamarine::IPointer::SHoldBeginEvent>(d);
|
||||
|
||||
pointerEvents.holdBegin.emit(SHoldBeginEvent{
|
||||
.timeMs = E->time_msec,
|
||||
.fingers = E->fingers,
|
||||
.timeMs = E.timeMs,
|
||||
.fingers = E.fingers,
|
||||
});
|
||||
});
|
||||
}, this, "CMouse");
|
||||
|
||||
hyprListener_holdEnd.initCallback(&mouse->events.hold_end, [this] (void* owner, void* data) {
|
||||
auto E = (wlr_pointer_hold_end_event*)data;
|
||||
listeners.holdEnd = mouse->events.holdEnd.registerListener([this](std::any d) {
|
||||
auto E = std::any_cast<Aquamarine::IPointer::SHoldEndEvent>(d);
|
||||
|
||||
pointerEvents.holdEnd.emit(SHoldEndEvent{
|
||||
.timeMs = E->time_msec,
|
||||
.cancelled = E->cancelled,
|
||||
.timeMs = E.timeMs,
|
||||
.cancelled = E.cancelled,
|
||||
});
|
||||
});
|
||||
}, this, "CMouse");
|
||||
|
||||
// clang-format on
|
||||
|
||||
deviceName = mouse->base.name ? mouse->base.name : "UNKNOWN";
|
||||
}
|
||||
|
||||
void CMouse::disconnectCallbacks() {
|
||||
hyprListener_destroy.removeCallback();
|
||||
hyprListener_motion.removeCallback();
|
||||
hyprListener_motionAbsolute.removeCallback();
|
||||
hyprListener_button.removeCallback();
|
||||
hyprListener_axis.removeCallback();
|
||||
hyprListener_frame.removeCallback();
|
||||
hyprListener_swipeBegin.removeCallback();
|
||||
hyprListener_swipeEnd.removeCallback();
|
||||
hyprListener_swipeUpdate.removeCallback();
|
||||
hyprListener_pinchBegin.removeCallback();
|
||||
hyprListener_pinchEnd.removeCallback();
|
||||
hyprListener_pinchUpdate.removeCallback();
|
||||
hyprListener_holdBegin.removeCallback();
|
||||
hyprListener_holdEnd.removeCallback();
|
||||
deviceName = mouse->getName();
|
||||
}
|
||||
|
||||
bool CMouse::isVirtual() {
|
||||
return false;
|
||||
}
|
||||
|
||||
wlr_pointer* CMouse::wlr() {
|
||||
return mouse;
|
||||
SP<Aquamarine::IPointer> CMouse::aq() {
|
||||
return mouse.lock();
|
||||
}
|
||||
|
@@ -4,33 +4,34 @@
|
||||
|
||||
class CMouse : public IPointer {
|
||||
public:
|
||||
static SP<CMouse> create(wlr_pointer* mouse);
|
||||
static SP<CMouse> create(SP<Aquamarine::IPointer> mouse);
|
||||
|
||||
virtual bool isVirtual();
|
||||
virtual wlr_pointer* wlr();
|
||||
virtual SP<Aquamarine::IPointer> aq();
|
||||
|
||||
private:
|
||||
CMouse(wlr_pointer* mouse);
|
||||
CMouse(SP<Aquamarine::IPointer> mouse);
|
||||
|
||||
wlr_pointer* mouse = nullptr;
|
||||
WP<Aquamarine::IPointer> mouse;
|
||||
|
||||
void disconnectCallbacks();
|
||||
struct {
|
||||
CHyprSignalListener destroy;
|
||||
|
||||
DYNLISTENER(destroy);
|
||||
DYNLISTENER(motion);
|
||||
DYNLISTENER(motionAbsolute);
|
||||
DYNLISTENER(button);
|
||||
DYNLISTENER(axis);
|
||||
DYNLISTENER(frame);
|
||||
CHyprSignalListener motion;
|
||||
CHyprSignalListener motionAbsolute;
|
||||
CHyprSignalListener button;
|
||||
CHyprSignalListener axis;
|
||||
CHyprSignalListener frame;
|
||||
|
||||
DYNLISTENER(swipeBegin);
|
||||
DYNLISTENER(swipeEnd);
|
||||
DYNLISTENER(swipeUpdate);
|
||||
CHyprSignalListener swipeBegin;
|
||||
CHyprSignalListener swipeEnd;
|
||||
CHyprSignalListener swipeUpdate;
|
||||
|
||||
DYNLISTENER(pinchBegin);
|
||||
DYNLISTENER(pinchEnd);
|
||||
DYNLISTENER(pinchUpdate);
|
||||
CHyprSignalListener pinchBegin;
|
||||
CHyprSignalListener pinchEnd;
|
||||
CHyprSignalListener pinchUpdate;
|
||||
|
||||
DYNLISTENER(holdBegin);
|
||||
DYNLISTENER(holdEnd);
|
||||
CHyprSignalListener holdBegin;
|
||||
CHyprSignalListener holdEnd;
|
||||
} listeners;
|
||||
};
|
||||
|
@@ -2,8 +2,9 @@
|
||||
#include "../defines.hpp"
|
||||
#include "../protocols/Tablet.hpp"
|
||||
#include "../protocols/core/Compositor.hpp"
|
||||
#include <aquamarine/input/Input.hpp>
|
||||
|
||||
SP<CTablet> CTablet::create(wlr_tablet* tablet) {
|
||||
SP<CTablet> CTablet::create(SP<Aquamarine::ITablet> tablet) {
|
||||
SP<CTablet> pTab = SP<CTablet>(new CTablet(tablet));
|
||||
|
||||
pTab->self = pTab;
|
||||
@@ -13,7 +14,7 @@ SP<CTablet> CTablet::create(wlr_tablet* tablet) {
|
||||
return pTab;
|
||||
}
|
||||
|
||||
SP<CTabletTool> CTabletTool::create(wlr_tablet_tool* tablet) {
|
||||
SP<CTabletTool> CTabletTool::create(SP<Aquamarine::ITabletTool> tablet) {
|
||||
SP<CTabletTool> pTab = SP<CTabletTool>(new CTabletTool(tablet));
|
||||
|
||||
pTab->self = pTab;
|
||||
@@ -23,7 +24,7 @@ SP<CTabletTool> CTabletTool::create(wlr_tablet_tool* tablet) {
|
||||
return pTab;
|
||||
}
|
||||
|
||||
SP<CTabletPad> CTabletPad::create(wlr_tablet_pad* tablet) {
|
||||
SP<CTabletPad> CTabletPad::create(SP<Aquamarine::ITabletPad> tablet) {
|
||||
SP<CTabletPad> pTab = SP<CTabletPad>(new CTabletPad(tablet));
|
||||
|
||||
pTab->self = pTab;
|
||||
@@ -33,33 +34,25 @@ SP<CTabletPad> CTabletPad::create(wlr_tablet_pad* tablet) {
|
||||
return pTab;
|
||||
}
|
||||
|
||||
SP<CTabletTool> CTabletTool::fromWlr(wlr_tablet_tool* tool) {
|
||||
return ((CTabletTool*)tool->data)->self.lock();
|
||||
}
|
||||
|
||||
SP<CTablet> CTablet::fromWlr(wlr_tablet* tablet) {
|
||||
return ((CTablet*)tablet->data)->self.lock();
|
||||
}
|
||||
|
||||
static uint32_t wlrUpdateToHl(uint32_t wlr) {
|
||||
static uint32_t aqUpdateToHl(uint32_t aq) {
|
||||
uint32_t result = 0;
|
||||
if (wlr & WLR_TABLET_TOOL_AXIS_X)
|
||||
if (aq & Aquamarine::AQ_TABLET_TOOL_AXIS_X)
|
||||
result |= CTablet::eTabletToolAxes::HID_TABLET_TOOL_AXIS_X;
|
||||
if (wlr & WLR_TABLET_TOOL_AXIS_Y)
|
||||
if (aq & Aquamarine::AQ_TABLET_TOOL_AXIS_Y)
|
||||
result |= CTablet::eTabletToolAxes::HID_TABLET_TOOL_AXIS_Y;
|
||||
if (wlr & WLR_TABLET_TOOL_AXIS_DISTANCE)
|
||||
if (aq & Aquamarine::AQ_TABLET_TOOL_AXIS_DISTANCE)
|
||||
result |= CTablet::eTabletToolAxes::HID_TABLET_TOOL_AXIS_DISTANCE;
|
||||
if (wlr & WLR_TABLET_TOOL_AXIS_PRESSURE)
|
||||
if (aq & Aquamarine::AQ_TABLET_TOOL_AXIS_PRESSURE)
|
||||
result |= CTablet::eTabletToolAxes::HID_TABLET_TOOL_AXIS_PRESSURE;
|
||||
if (wlr & WLR_TABLET_TOOL_AXIS_TILT_X)
|
||||
if (aq & Aquamarine::AQ_TABLET_TOOL_AXIS_TILT_X)
|
||||
result |= CTablet::eTabletToolAxes::HID_TABLET_TOOL_AXIS_TILT_X;
|
||||
if (wlr & WLR_TABLET_TOOL_AXIS_TILT_Y)
|
||||
if (aq & Aquamarine::AQ_TABLET_TOOL_AXIS_TILT_Y)
|
||||
result |= CTablet::eTabletToolAxes::HID_TABLET_TOOL_AXIS_TILT_Y;
|
||||
if (wlr & WLR_TABLET_TOOL_AXIS_ROTATION)
|
||||
if (aq & Aquamarine::AQ_TABLET_TOOL_AXIS_ROTATION)
|
||||
result |= CTablet::eTabletToolAxes::HID_TABLET_TOOL_AXIS_ROTATION;
|
||||
if (wlr & WLR_TABLET_TOOL_AXIS_SLIDER)
|
||||
if (aq & Aquamarine::AQ_TABLET_TOOL_AXIS_SLIDER)
|
||||
result |= CTablet::eTabletToolAxes::HID_TABLET_TOOL_AXIS_SLIDER;
|
||||
if (wlr & WLR_TABLET_TOOL_AXIS_WHEEL)
|
||||
if (aq & Aquamarine::AQ_TABLET_TOOL_AXIS_WHEEL)
|
||||
result |= CTablet::eTabletToolAxes::HID_TABLET_TOOL_AXIS_WHEEL;
|
||||
return result;
|
||||
}
|
||||
@@ -68,97 +61,81 @@ uint32_t CTablet::getCapabilities() {
|
||||
return HID_INPUT_CAPABILITY_POINTER | HID_INPUT_CAPABILITY_TABLET;
|
||||
}
|
||||
|
||||
wlr_tablet* CTablet::wlr() {
|
||||
return tablet;
|
||||
SP<Aquamarine::ITablet> CTablet::aq() {
|
||||
return tablet.lock();
|
||||
}
|
||||
|
||||
CTablet::CTablet(wlr_tablet* tablet_) : tablet(tablet_) {
|
||||
CTablet::CTablet(SP<Aquamarine::ITablet> tablet_) : tablet(tablet_) {
|
||||
if (!tablet)
|
||||
return;
|
||||
|
||||
tablet->data = this;
|
||||
|
||||
// clang-format off
|
||||
hyprListener_destroy.initCallback(&tablet->base.events.destroy, [this] (void* owner, void* data) {
|
||||
tablet = nullptr;
|
||||
disconnectCallbacks();
|
||||
listeners.destroy = tablet->events.destroy.registerListener([this](std::any d) {
|
||||
tablet.reset();
|
||||
events.destroy.emit();
|
||||
}, this, "CTablet");
|
||||
});
|
||||
|
||||
hyprListener_axis.initCallback(&tablet->events.axis, [this] (void* owner, void* data) {
|
||||
auto E = (wlr_tablet_tool_axis_event*)data;
|
||||
listeners.axis = tablet->events.axis.registerListener([this](std::any d) {
|
||||
auto E = std::any_cast<Aquamarine::ITablet::SAxisEvent>(d);
|
||||
|
||||
tabletEvents.axis.emit(SAxisEvent{
|
||||
.tool = E->tool,
|
||||
.tool = E.tool,
|
||||
.tablet = self.lock(),
|
||||
.timeMs = E->time_msec,
|
||||
.updatedAxes = wlrUpdateToHl(E->updated_axes),
|
||||
.axis = {E->x, E->y},
|
||||
.axisDelta = {E->dx, E->dy},
|
||||
.tilt = {E->tilt_x, E->tilt_y},
|
||||
.pressure = E->pressure,
|
||||
.distance = E->distance,
|
||||
.rotation = E->rotation,
|
||||
.slider = E->slider,
|
||||
.wheelDelta = E->wheel_delta,
|
||||
.timeMs = E.timeMs,
|
||||
.updatedAxes = aqUpdateToHl(E.updatedAxes),
|
||||
.axis = E.absolute,
|
||||
.axisDelta = E.delta,
|
||||
.tilt = E.tilt,
|
||||
.pressure = E.pressure,
|
||||
.distance = E.distance,
|
||||
.rotation = E.rotation,
|
||||
.slider = E.slider,
|
||||
.wheelDelta = E.wheelDelta,
|
||||
});
|
||||
});
|
||||
}, this, "CTablet");
|
||||
|
||||
hyprListener_proximity.initCallback(&tablet->events.proximity, [this] (void* owner, void* data) {
|
||||
auto E = (wlr_tablet_tool_proximity_event*)data;
|
||||
listeners.proximity = tablet->events.proximity.registerListener([this](std::any d) {
|
||||
auto E = std::any_cast<Aquamarine::ITablet::SProximityEvent>(d);
|
||||
|
||||
tabletEvents.proximity.emit(SProximityEvent{
|
||||
.tool = E->tool,
|
||||
.tool = E.tool,
|
||||
.tablet = self.lock(),
|
||||
.timeMs = E->time_msec,
|
||||
.proximity = {E->x, E->y},
|
||||
.in = E->state == WLR_TABLET_TOOL_PROXIMITY_IN,
|
||||
.timeMs = E.timeMs,
|
||||
.proximity = E.absolute,
|
||||
.in = E.in,
|
||||
});
|
||||
});
|
||||
}, this, "CTablet");
|
||||
|
||||
hyprListener_tip.initCallback(&tablet->events.tip, [this] (void* owner, void* data) {
|
||||
auto E = (wlr_tablet_tool_tip_event*)data;
|
||||
listeners.tip = tablet->events.tip.registerListener([this](std::any d) {
|
||||
auto E = std::any_cast<Aquamarine::ITablet::STipEvent>(d);
|
||||
|
||||
tabletEvents.tip.emit(STipEvent{
|
||||
.tool = E->tool,
|
||||
.tool = E.tool,
|
||||
.tablet = self.lock(),
|
||||
.timeMs = E->time_msec,
|
||||
.tip = {E->x, E->y},
|
||||
.in = E->state == WLR_TABLET_TOOL_TIP_DOWN,
|
||||
.timeMs = E.timeMs,
|
||||
.tip = E.absolute,
|
||||
.in = E.down,
|
||||
});
|
||||
});
|
||||
}, this, "CTablet");
|
||||
|
||||
hyprListener_button.initCallback(&tablet->events.button, [this] (void* owner, void* data) {
|
||||
auto E = (wlr_tablet_tool_button_event*)data;
|
||||
listeners.button = tablet->events.button.registerListener([this](std::any d) {
|
||||
auto E = std::any_cast<Aquamarine::ITablet::SButtonEvent>(d);
|
||||
|
||||
tabletEvents.button.emit(SButtonEvent{
|
||||
.tool = E->tool,
|
||||
.tool = E.tool,
|
||||
.tablet = self.lock(),
|
||||
.timeMs = E->time_msec,
|
||||
.button = E->button,
|
||||
.down = E->state == WLR_BUTTON_PRESSED,
|
||||
.timeMs = E.timeMs,
|
||||
.button = E.button,
|
||||
.down = E.down,
|
||||
});
|
||||
});
|
||||
}, this, "CTablet");
|
||||
// clang-format on
|
||||
|
||||
deviceName = tablet->base.name ? tablet->base.name : "UNKNOWN";
|
||||
deviceName = tablet->getName();
|
||||
}
|
||||
|
||||
CTablet::~CTablet() {
|
||||
if (tablet)
|
||||
tablet->data = nullptr;
|
||||
|
||||
PROTO::tablet->recheckRegisteredDevices();
|
||||
}
|
||||
|
||||
void CTablet::disconnectCallbacks() {
|
||||
hyprListener_axis.removeCallback();
|
||||
hyprListener_button.removeCallback();
|
||||
hyprListener_destroy.removeCallback();
|
||||
hyprListener_proximity.removeCallback();
|
||||
hyprListener_tip.removeCallback();
|
||||
}
|
||||
|
||||
eHIDType CTablet::getType() {
|
||||
return HID_TYPE_TABLET;
|
||||
}
|
||||
@@ -167,138 +144,111 @@ uint32_t CTabletPad::getCapabilities() {
|
||||
return HID_INPUT_CAPABILITY_TABLET;
|
||||
}
|
||||
|
||||
wlr_tablet_pad* CTabletPad::wlr() {
|
||||
return pad;
|
||||
SP<Aquamarine::ITabletPad> CTabletPad::aq() {
|
||||
return pad.lock();
|
||||
}
|
||||
|
||||
eHIDType CTabletPad::getType() {
|
||||
return HID_TYPE_TABLET_PAD;
|
||||
}
|
||||
|
||||
CTabletPad::CTabletPad(wlr_tablet_pad* pad_) : pad(pad_) {
|
||||
CTabletPad::CTabletPad(SP<Aquamarine::ITabletPad> pad_) : pad(pad_) {
|
||||
if (!pad)
|
||||
return;
|
||||
|
||||
// clang-format off
|
||||
hyprListener_destroy.initCallback(&pad->base.events.destroy, [this] (void* owner, void* data) {
|
||||
pad = nullptr;
|
||||
disconnectCallbacks();
|
||||
listeners.destroy = pad->events.destroy.registerListener([this](std::any d) {
|
||||
pad.reset();
|
||||
events.destroy.emit();
|
||||
}, this, "CTabletPad");
|
||||
});
|
||||
|
||||
hyprListener_button.initCallback(&pad->events.button, [this] (void* owner, void* data) {
|
||||
auto E = (wlr_tablet_pad_button_event*)data;
|
||||
listeners.button = pad->events.button.registerListener([this](std::any d) {
|
||||
auto E = std::any_cast<Aquamarine::ITabletPad::SButtonEvent>(d);
|
||||
|
||||
padEvents.button.emit(SButtonEvent{
|
||||
.timeMs = E->time_msec,
|
||||
.button = E->button,
|
||||
.down = E->state == WLR_BUTTON_PRESSED,
|
||||
.mode = E->mode,
|
||||
.group = E->group,
|
||||
.timeMs = E.timeMs,
|
||||
.button = E.button,
|
||||
.down = E.down,
|
||||
.mode = E.mode,
|
||||
.group = E.group,
|
||||
});
|
||||
});
|
||||
}, this, "CTabletPad");
|
||||
|
||||
hyprListener_ring.initCallback(&pad->events.ring, [this] (void* owner, void* data) {
|
||||
auto E = (wlr_tablet_pad_ring_event*)data;
|
||||
listeners.ring = pad->events.ring.registerListener([this](std::any d) {
|
||||
auto E = std::any_cast<Aquamarine::ITabletPad::SRingEvent>(d);
|
||||
|
||||
padEvents.ring.emit(SRingEvent{
|
||||
.timeMs = E->time_msec,
|
||||
.finger = E->source == WLR_TABLET_PAD_RING_SOURCE_FINGER,
|
||||
.ring = E->ring,
|
||||
.position = E->position,
|
||||
.mode = E->mode,
|
||||
.timeMs = E.timeMs,
|
||||
.finger = E.source == Aquamarine::ITabletPad::AQ_TABLET_PAD_RING_SOURCE_FINGER,
|
||||
.ring = E.ring,
|
||||
.position = E.pos,
|
||||
.mode = E.mode,
|
||||
});
|
||||
});
|
||||
}, this, "CTabletPad");
|
||||
|
||||
hyprListener_strip.initCallback(&pad->events.strip, [this] (void* owner, void* data) {
|
||||
auto E = (wlr_tablet_pad_strip_event*)data;
|
||||
listeners.strip = pad->events.strip.registerListener([this](std::any d) {
|
||||
auto E = std::any_cast<Aquamarine::ITabletPad::SStripEvent>(d);
|
||||
|
||||
padEvents.strip.emit(SStripEvent{
|
||||
.timeMs = E->time_msec,
|
||||
.finger = E->source == WLR_TABLET_PAD_STRIP_SOURCE_FINGER,
|
||||
.strip = E->strip,
|
||||
.position = E->position,
|
||||
.mode = E->mode,
|
||||
.timeMs = E.timeMs,
|
||||
.finger = E.source == Aquamarine::ITabletPad::AQ_TABLET_PAD_STRIP_SOURCE_FINGER,
|
||||
.strip = E.strip,
|
||||
.position = E.pos,
|
||||
.mode = E.mode,
|
||||
});
|
||||
});
|
||||
}, this, "CTabletPad");
|
||||
|
||||
hyprListener_attach.initCallback(&pad->events.attach_tablet, [this] (void* owner, void* data) {
|
||||
if (!data)
|
||||
return;
|
||||
listeners.attach = pad->events.attach.registerListener([this](std::any d) {
|
||||
; // TODO: this doesn't do anything in aq atm
|
||||
});
|
||||
|
||||
padEvents.attach.emit(CTabletTool::fromWlr((wlr_tablet_tool*)data));
|
||||
}, this, "CTabletPad");
|
||||
// clang-format on
|
||||
|
||||
deviceName = pad->base.name ? pad->base.name : "UNKNOWN";
|
||||
deviceName = pad->getName();
|
||||
}
|
||||
|
||||
CTabletPad::~CTabletPad() {
|
||||
PROTO::tablet->recheckRegisteredDevices();
|
||||
}
|
||||
|
||||
void CTabletPad::disconnectCallbacks() {
|
||||
hyprListener_ring.removeCallback();
|
||||
hyprListener_button.removeCallback();
|
||||
hyprListener_destroy.removeCallback();
|
||||
hyprListener_strip.removeCallback();
|
||||
hyprListener_attach.removeCallback();
|
||||
}
|
||||
|
||||
uint32_t CTabletTool::getCapabilities() {
|
||||
return HID_INPUT_CAPABILITY_POINTER | HID_INPUT_CAPABILITY_TABLET;
|
||||
}
|
||||
|
||||
wlr_tablet_tool* CTabletTool::wlr() {
|
||||
return tool;
|
||||
SP<Aquamarine::ITabletTool> CTabletTool::aq() {
|
||||
return tool.lock();
|
||||
}
|
||||
|
||||
eHIDType CTabletTool::getType() {
|
||||
return HID_TYPE_TABLET_TOOL;
|
||||
}
|
||||
|
||||
CTabletTool::CTabletTool(wlr_tablet_tool* tool_) : tool(tool_) {
|
||||
CTabletTool::CTabletTool(SP<Aquamarine::ITabletTool> tool_) : tool(tool_) {
|
||||
if (!tool)
|
||||
return;
|
||||
|
||||
// clang-format off
|
||||
hyprListener_destroy.initCallback(&tool->events.destroy, [this] (void* owner, void* data) {
|
||||
tool = nullptr;
|
||||
disconnectCallbacks();
|
||||
listeners.destroyTool = tool->events.destroy.registerListener([this](std::any d) {
|
||||
tool.reset();
|
||||
events.destroy.emit();
|
||||
}, this, "CTabletTool");
|
||||
// clang-format on
|
||||
});
|
||||
|
||||
if (tool->tilt)
|
||||
if (tool->capabilities & Aquamarine::ITabletTool::AQ_TABLET_TOOL_CAPABILITY_TILT)
|
||||
toolCapabilities |= HID_TABLET_TOOL_CAPABILITY_TILT;
|
||||
if (tool->pressure)
|
||||
if (tool->capabilities & Aquamarine::ITabletTool::AQ_TABLET_TOOL_CAPABILITY_PRESSURE)
|
||||
toolCapabilities |= HID_TABLET_TOOL_CAPABILITY_PRESSURE;
|
||||
if (tool->distance)
|
||||
if (tool->capabilities & Aquamarine::ITabletTool::AQ_TABLET_TOOL_CAPABILITY_DISTANCE)
|
||||
toolCapabilities |= HID_TABLET_TOOL_CAPABILITY_DISTANCE;
|
||||
if (tool->rotation)
|
||||
if (tool->capabilities & Aquamarine::ITabletTool::AQ_TABLET_TOOL_CAPABILITY_ROTATION)
|
||||
toolCapabilities |= HID_TABLET_TOOL_CAPABILITY_ROTATION;
|
||||
if (tool->slider)
|
||||
if (tool->capabilities & Aquamarine::ITabletTool::AQ_TABLET_TOOL_CAPABILITY_SLIDER)
|
||||
toolCapabilities |= HID_TABLET_TOOL_CAPABILITY_SLIDER;
|
||||
if (tool->wheel)
|
||||
if (tool->capabilities & Aquamarine::ITabletTool::AQ_TABLET_TOOL_CAPABILITY_WHEEL)
|
||||
toolCapabilities |= HID_TABLET_TOOL_CAPABILITY_WHEEL;
|
||||
|
||||
tool->data = this;
|
||||
|
||||
deviceName = std::to_string(tool->hardware_serial) + std::to_string(tool->hardware_wacom);
|
||||
deviceName = std::format("{:x}-{:x}", tool->serial, tool->id);
|
||||
}
|
||||
|
||||
CTabletTool::~CTabletTool() {
|
||||
if (tool)
|
||||
tool->data = nullptr;
|
||||
|
||||
PROTO::tablet->recheckRegisteredDevices();
|
||||
}
|
||||
|
||||
void CTabletTool::disconnectCallbacks() {
|
||||
hyprListener_destroy.removeCallback();
|
||||
listeners.destroySurface.reset();
|
||||
}
|
||||
|
||||
SP<CWLSurfaceResource> CTabletTool::getSurface() {
|
||||
return pSurface.lock();
|
||||
}
|
||||
|
@@ -1,14 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include "IHID.hpp"
|
||||
#include "../helpers/WLListener.hpp"
|
||||
#include "../macros.hpp"
|
||||
#include "../helpers/Vector2D.hpp"
|
||||
#include "../helpers/Box.hpp"
|
||||
#include "../helpers/math/Math.hpp"
|
||||
#include "../helpers/math/Math.hpp"
|
||||
|
||||
struct wlr_tablet;
|
||||
struct wlr_tablet_tool;
|
||||
struct wlr_tablet_pad;
|
||||
AQUAMARINE_FORWARD(ITablet);
|
||||
AQUAMARINE_FORWARD(ITabletTool);
|
||||
AQUAMARINE_FORWARD(ITabletPad);
|
||||
|
||||
class CTabletTool;
|
||||
class CTabletPad;
|
||||
@@ -21,13 +20,12 @@ class CWLSurfaceResource;
|
||||
*/
|
||||
class CTablet : public IHID {
|
||||
public:
|
||||
static SP<CTablet> create(wlr_tablet* tablet);
|
||||
static SP<CTablet> fromWlr(wlr_tablet* tablet);
|
||||
static SP<CTablet> create(SP<Aquamarine::ITablet> tablet);
|
||||
~CTablet();
|
||||
|
||||
virtual uint32_t getCapabilities();
|
||||
virtual eHIDType getType();
|
||||
wlr_tablet* wlr();
|
||||
SP<Aquamarine::ITablet> aq();
|
||||
|
||||
enum eTabletToolAxes {
|
||||
HID_TABLET_TOOL_AXIS_X = (1 << 0),
|
||||
@@ -42,7 +40,7 @@ class CTablet : public IHID {
|
||||
};
|
||||
|
||||
struct SAxisEvent {
|
||||
wlr_tablet_tool* tool;
|
||||
SP<Aquamarine::ITabletTool> tool;
|
||||
SP<CTablet> tablet;
|
||||
|
||||
uint32_t timeMs = 0;
|
||||
@@ -58,7 +56,7 @@ class CTablet : public IHID {
|
||||
};
|
||||
|
||||
struct SProximityEvent {
|
||||
wlr_tablet_tool* tool;
|
||||
SP<Aquamarine::ITabletTool> tool;
|
||||
SP<CTablet> tablet;
|
||||
|
||||
uint32_t timeMs = 0;
|
||||
@@ -67,7 +65,7 @@ class CTablet : public IHID {
|
||||
};
|
||||
|
||||
struct STipEvent {
|
||||
wlr_tablet_tool* tool;
|
||||
SP<Aquamarine::ITabletTool> tool;
|
||||
SP<CTablet> tablet;
|
||||
|
||||
uint32_t timeMs = 0;
|
||||
@@ -76,7 +74,7 @@ class CTablet : public IHID {
|
||||
};
|
||||
|
||||
struct SButtonEvent {
|
||||
wlr_tablet_tool* tool;
|
||||
SP<Aquamarine::ITabletTool> tool;
|
||||
SP<CTablet> tablet;
|
||||
|
||||
uint32_t timeMs = 0;
|
||||
@@ -100,27 +98,27 @@ class CTablet : public IHID {
|
||||
CBox boundBox; // output-local
|
||||
|
||||
private:
|
||||
CTablet(wlr_tablet* tablet);
|
||||
CTablet(SP<Aquamarine::ITablet> tablet);
|
||||
|
||||
void disconnectCallbacks();
|
||||
WP<Aquamarine::ITablet> tablet;
|
||||
|
||||
wlr_tablet* tablet = nullptr;
|
||||
|
||||
DYNLISTENER(destroy);
|
||||
DYNLISTENER(axis);
|
||||
DYNLISTENER(proximity);
|
||||
DYNLISTENER(tip);
|
||||
DYNLISTENER(button);
|
||||
struct {
|
||||
CHyprSignalListener destroy;
|
||||
CHyprSignalListener axis;
|
||||
CHyprSignalListener proximity;
|
||||
CHyprSignalListener tip;
|
||||
CHyprSignalListener button;
|
||||
} listeners;
|
||||
};
|
||||
|
||||
class CTabletPad : public IHID {
|
||||
public:
|
||||
static SP<CTabletPad> create(wlr_tablet_pad* pad);
|
||||
static SP<CTabletPad> create(SP<Aquamarine::ITabletPad> pad);
|
||||
~CTabletPad();
|
||||
|
||||
virtual uint32_t getCapabilities();
|
||||
virtual eHIDType getType();
|
||||
wlr_tablet_pad* wlr();
|
||||
SP<Aquamarine::ITabletPad> aq();
|
||||
|
||||
struct SButtonEvent {
|
||||
uint32_t timeMs = 0;
|
||||
@@ -159,23 +157,22 @@ class CTabletPad : public IHID {
|
||||
std::string hlName;
|
||||
|
||||
private:
|
||||
CTabletPad(wlr_tablet_pad* pad);
|
||||
CTabletPad(SP<Aquamarine::ITabletPad> pad);
|
||||
|
||||
void disconnectCallbacks();
|
||||
WP<Aquamarine::ITabletPad> pad;
|
||||
|
||||
wlr_tablet_pad* pad = nullptr;
|
||||
|
||||
DYNLISTENER(destroy);
|
||||
DYNLISTENER(ring);
|
||||
DYNLISTENER(strip);
|
||||
DYNLISTENER(button);
|
||||
DYNLISTENER(attach);
|
||||
struct {
|
||||
CHyprSignalListener destroy;
|
||||
CHyprSignalListener ring;
|
||||
CHyprSignalListener strip;
|
||||
CHyprSignalListener button;
|
||||
CHyprSignalListener attach;
|
||||
} listeners;
|
||||
};
|
||||
|
||||
class CTabletTool : public IHID {
|
||||
public:
|
||||
static SP<CTabletTool> create(wlr_tablet_tool* tool);
|
||||
static SP<CTabletTool> fromWlr(wlr_tablet_tool* tool);
|
||||
static SP<CTabletTool> create(SP<Aquamarine::ITabletTool> tool);
|
||||
~CTabletTool();
|
||||
|
||||
enum eTabletToolType {
|
||||
@@ -199,7 +196,7 @@ class CTabletTool : public IHID {
|
||||
};
|
||||
|
||||
virtual uint32_t getCapabilities();
|
||||
wlr_tablet_tool* wlr();
|
||||
SP<Aquamarine::ITabletTool> aq();
|
||||
virtual eHIDType getType();
|
||||
SP<CWLSurfaceResource> getSurface();
|
||||
void setSurface(SP<CWLSurfaceResource>);
|
||||
@@ -216,17 +213,13 @@ class CTabletTool : public IHID {
|
||||
std::string hlName;
|
||||
|
||||
private:
|
||||
CTabletTool(wlr_tablet_tool* tool);
|
||||
|
||||
void disconnectCallbacks();
|
||||
CTabletTool(SP<Aquamarine::ITabletTool> tool);
|
||||
|
||||
WP<CWLSurfaceResource> pSurface;
|
||||
|
||||
wlr_tablet_tool* tool = nullptr;
|
||||
|
||||
DYNLISTENER(destroy);
|
||||
WP<Aquamarine::ITabletTool> tool;
|
||||
|
||||
struct {
|
||||
CHyprSignalListener destroySurface;
|
||||
CHyprSignalListener destroyTool;
|
||||
} listeners;
|
||||
};
|