Compare commits
486 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
788ae58897 | ||
|
bba2d9a197 | ||
|
e340e9f431 | ||
|
c2d14a2013 | ||
|
95cdedee04 | ||
|
0706c1a1f7 | ||
|
aecf1abddd | ||
|
b9f82e9968 | ||
|
e06b520427 | ||
|
dab50b3ef3 | ||
|
eaac5c7cbd | ||
|
a5234f26e4 | ||
|
de3ad245dc | ||
|
db24964877 | ||
|
9f7a96b997 | ||
|
3cba4ba44e | ||
|
8237627f3a | ||
|
35e134e570 | ||
|
452a7e6905 | ||
|
61a51bb4ef | ||
|
aefaeedf5e | ||
|
cef5e6dd7c | ||
|
7c03e9d376 | ||
|
df956a0f6f | ||
|
33f271c29a | ||
|
e892310953 | ||
|
4d05677e8d | ||
|
c16044a5c8 | ||
|
d94d8b4ab2 | ||
|
bb5c3f2702 | ||
|
0a27af8cd1 | ||
|
c106f454c1 | ||
|
875b598a33 | ||
|
8bbeee1173 | ||
|
b1e5cc66bd | ||
|
5ff02902ee | ||
|
cccca7c02e | ||
|
10a4365f7d | ||
|
a7a6eedc21 | ||
|
888bdf4e23 | ||
|
ceef4fb3a5 | ||
|
22f7d6f142 | ||
|
f9e4998a6d | ||
|
3c617ce33c | ||
|
f6ac755cf7 | ||
|
320144ae72 | ||
|
92186898c0 | ||
|
10a9fec7fc | ||
|
6d7544458d | ||
|
d26439a0fe | ||
|
ef6b0c81c9 | ||
|
8f83d29f00 | ||
|
22bf2853e6 | ||
|
5963970be5 | ||
|
8b51eeb7ae | ||
|
5329298b52 | ||
|
e9a7fb8f91 | ||
|
1fb720b62a | ||
|
2687788236 | ||
|
0ddb952d7a | ||
|
1930a95000 | ||
|
cc38e7e18f | ||
|
55ec8bd512 | ||
|
54f57797e9 | ||
|
65f66dcf0d | ||
|
451d7a41fc | ||
|
00d6261cc0 | ||
|
745a82ce8a | ||
|
a847bc67b1 | ||
|
b100344595 | ||
|
943b3d467b | ||
|
940f7aa990 | ||
|
e5fa017172 | ||
|
c4eda46d0e | ||
|
aa067a4cf1 | ||
|
67cee43006 | ||
|
47a1650c48 | ||
|
936dfedbad | ||
|
6113f4da7f | ||
|
cc923ad031 | ||
|
df9ff44899 | ||
|
97493511f9 | ||
|
505c1f8f4a | ||
|
6744bb57c6 | ||
|
2259a88551 | ||
|
1ba050d603 | ||
|
e8717a4fce | ||
|
9b03307653 | ||
|
b735295d2b | ||
|
8d5cdedbd3 | ||
|
4f591e807a | ||
|
fb91c2550f | ||
|
0ddbd1c3a4 | ||
|
af83c82513 | ||
|
9d37b1b073 | ||
|
cf18eca86d | ||
|
ec1e6be003 | ||
|
83be2480c4 | ||
|
7affc34ab4 | ||
|
098e491a43 | ||
|
967fe76a60 | ||
|
940ed3d525 | ||
|
6f7280a690 | ||
|
20031cea92 | ||
|
3fb47372b7 | ||
|
bb160cfe37 | ||
|
a29cfa7843 | ||
|
f5fa84554f | ||
|
b88e4a1a9a | ||
|
ff411658e8 | ||
|
943c7d18cc | ||
|
ccfae82ad1 | ||
|
430b5c302a | ||
|
8fa4cfb7df | ||
|
a551f85b91 | ||
|
07052a515b | ||
|
1fa0cd7a75 | ||
|
c10739e6e3 | ||
|
9e628067fc | ||
|
99b01c5d12 | ||
|
a8ff3a452c | ||
|
dca75db127 | ||
|
a425fbebe4 | ||
|
cca227a53e | ||
|
b9c439a55e | ||
|
726d697821 | ||
|
0ccc0ace88 | ||
|
f43d4a8638 | ||
|
4c7a2faf85 | ||
|
3b66351eeb | ||
|
e58e97b0a3 | ||
|
2dd0b2af71 | ||
|
2ec2b3bfb3 | ||
|
0ec128e5ed | ||
|
083a5cf3c1 | ||
|
8f42401aa8 | ||
|
97a309b784 | ||
|
3bf6f78dad | ||
|
e4ab28b1fb | ||
|
81ad218b8b | ||
|
64c46db087 | ||
|
0920572e70 | ||
|
55ccb1a8cf | ||
|
d1638a09ba | ||
|
e3882b23d0 | ||
|
88e9e03945 | ||
|
0fb9a04526 | ||
|
44899cd548 | ||
|
cd0d049126 | ||
|
180c26ada6 | ||
|
5833abbbd1 | ||
|
514e0ff509 | ||
|
40081cb330 | ||
|
32b18179dd | ||
|
29e7dc6428 | ||
|
3c0605c68e | ||
|
d8b865366a | ||
|
3852418d24 | ||
|
c4d214c42d | ||
|
93b4478e70 | ||
|
7c7a84ff60 | ||
|
a0b2169ed6 | ||
|
ee91df62f0 | ||
|
12c1bb936d | ||
|
5f721dce36 | ||
|
d679d20029 | ||
|
7188ee4f99 | ||
|
c7315617eb | ||
|
d49a1334a8 | ||
|
2c481202ef | ||
|
6cf193e166 | ||
|
b1120ec433 | ||
|
5d4b54b012 | ||
|
b6e226c320 | ||
|
f9b52203f5 | ||
|
a3d3b4fd64 | ||
|
f3f7d3629a | ||
|
c356e42500 | ||
|
0b29caf9ab | ||
|
3dd8db83f1 | ||
|
d5689bb539 | ||
|
e5384774a8 | ||
|
f0e023bff2 | ||
|
3cec45d821 | ||
|
7f46680ab1 | ||
|
f603a22af0 | ||
|
cdac64970e | ||
|
6e0aadc585 | ||
|
2b6ff6837e | ||
|
29997ef4ba | ||
|
5e96d738e6 | ||
|
9df0f0b66c | ||
|
4093b993a2 | ||
|
08cc063e17 | ||
|
a17850e41c | ||
|
6a5c342063 | ||
|
f044e4c951 | ||
|
ce3ba798df | ||
|
0eaf3581a3 | ||
|
62ee5cc273 | ||
|
48bf32c5de | ||
|
904f9b6aee | ||
|
e5d3a71263 | ||
|
0e630e9e74 | ||
|
5f30cb7753 | ||
|
495b92fb53 | ||
|
b57086aa43 | ||
|
09581d32fd | ||
|
86e9f69a69 | ||
|
781828a56e | ||
|
0baf166d39 | ||
|
ace803948a | ||
|
01c2ff34dd | ||
|
22b1370ae5 | ||
|
f309681d4a | ||
|
ce62521883 | ||
|
e7fd0f5aec | ||
|
abfd550ee2 | ||
|
8e51a36c7f | ||
|
5c3bd8e93d | ||
|
05a5e0b4f1 | ||
|
b61d4c3636 | ||
|
e79d3cd2ef | ||
|
1822707c7e | ||
|
c3f7c9bbb5 | ||
|
ee8116ac5d | ||
|
f5db483973 | ||
|
7564b26b7d | ||
|
178a300eea | ||
|
d655a10381 | ||
|
b65773bea9 | ||
|
c4eb194033 | ||
|
6ae89940c7 | ||
|
3d28879c26 | ||
|
223dcc8bac | ||
|
6ce07ee864 | ||
|
bc299928ad | ||
|
ac658500fb | ||
|
8cced091f5 | ||
|
91299f7039 | ||
|
60308a2bb5 | ||
|
613eac4603 | ||
|
e4a26f4f1d | ||
|
57b632ead8 | ||
|
1bf63dfdcd | ||
|
e0cfbec66b | ||
|
b3a7e3109b | ||
|
45e82199fb | ||
|
4711796d38 | ||
|
0d70c44253 | ||
|
a364df4c9e | ||
|
46d990f1b6 | ||
|
5bf7b1e1fa | ||
|
97444ed7a8 | ||
|
4e41cda27e | ||
|
da86aac0f5 | ||
|
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 |
101
.clang-tidy
Normal file
@@ -0,0 +1,101 @@
|
||||
WarningsAsErrors: '*'
|
||||
HeaderFilterRegex: '.*\.hpp'
|
||||
FormatStyle: file
|
||||
Checks: >
|
||||
-*,
|
||||
bugprone-*,
|
||||
-bugprone-easily-swappable-parameters,
|
||||
-bugprone-forward-declararion-namespace,
|
||||
-bugprone-forward-declararion-namespace,
|
||||
-bugprone-macro-parentheses,
|
||||
-bugprone-narrowing-conversions,
|
||||
-bugprone-branch-clone,
|
||||
-bugprone-assignment-in-if-condition,
|
||||
concurrency-*,
|
||||
-concurrency-mt-unsafe,
|
||||
cppcoreguidelines-*,
|
||||
-cppcoreguidelines-owning-memory,
|
||||
-cppcoreguidelines-avoid-magic-numbers,
|
||||
-cppcoreguidelines-pro-bounds-constant-array-index,
|
||||
-cppcoreguidelines-avoid-const-or-ref-data-members,
|
||||
-cppcoreguidelines-non-private-member-variables-in-classes,
|
||||
-cppcoreguidelines-avoid-goto,
|
||||
-cppcoreguidelines-pro-bounds-array-to-pointer-decay,
|
||||
-cppcoreguidelines-avoid-do-while,
|
||||
-cppcoreguidelines-avoid-non-const-global-variables,
|
||||
-cppcoreguidelines-special-member-functions,
|
||||
-cppcoreguidelines-explicit-virtual-functions,
|
||||
-cppcoreguidelines-avoid-c-arrays,
|
||||
-cppcoreguidelines-pro-bounds-pointer-arithmetic,
|
||||
-cppcoreguidelines-narrowing-conversions,
|
||||
-cppcoreguidelines-pro-type-union-access,
|
||||
-cppcoreguidelines-pro-type-member-init,
|
||||
-cppcoreguidelines-macro-usage,
|
||||
-cppcoreguidelines-macro-to-enum,
|
||||
-cppcoreguidelines-init-variables,
|
||||
-cppcoreguidelines-pro-type-cstyle-cast,
|
||||
-cppcoreguidelines-pro-type-vararg,
|
||||
-cppcoreguidelines-pro-type-reinterpret-cast,
|
||||
google-global-names-in-headers,
|
||||
-google-readability-casting,
|
||||
google-runtime-operator,
|
||||
misc-*,
|
||||
-misc-unused-parameters,
|
||||
-misc-no-recursion,
|
||||
-misc-non-private-member-variables-in-classes,
|
||||
-misc-include-cleaner,
|
||||
-misc-use-anonymous-namespace,
|
||||
-misc-const-correctness,
|
||||
modernize-*,
|
||||
-modernize-return-braced-init-list,
|
||||
-modernize-use-trailing-return-type,
|
||||
-modernize-use-using,
|
||||
-modernize-use-override,
|
||||
-modernize-avoid-c-arrays,
|
||||
-modernize-macro-to-enum,
|
||||
-modernize-loop-convert,
|
||||
-modernize-use-nodiscard,
|
||||
-modernize-pass-by-value,
|
||||
-modernize-use-auto,
|
||||
performance-*,
|
||||
-performance-avoid-endl,
|
||||
-performance-unnecessary-value-param,
|
||||
portability-std-allocator-const,
|
||||
readability-*,
|
||||
-readability-function-cognitive-complexity,
|
||||
-readability-function-size,
|
||||
-readability-identifier-length,
|
||||
-readability-magic-numbers,
|
||||
-readability-uppercase-literal-suffix,
|
||||
-readability-braces-around-statements,
|
||||
-readability-redundant-access-specifiers,
|
||||
-readability-else-after-return,
|
||||
-readability-container-data-pointer,
|
||||
-readability-implicit-bool-conversion,
|
||||
-readability-avoid-nested-conditional-operator,
|
||||
-readability-redundant-member-init,
|
||||
-readability-redundant-string-init,
|
||||
-readability-avoid-const-params-in-decls,
|
||||
-readability-named-parameter,
|
||||
-readability-convert-member-functions-to-static,
|
||||
-readability-qualified-auto,
|
||||
-readability-make-member-function-const,
|
||||
-readability-isolate-declaration,
|
||||
-readability-inconsistent-declaration-parameter-name,
|
||||
-clang-diagnostic-error,
|
||||
|
||||
CheckOptions:
|
||||
performance-for-range-copy.WarnOnAllAutoCopies: true
|
||||
performance-inefficient-string-concatenation.StrictMode: true
|
||||
readability-braces-around-statements.ShortStatementLines: 0
|
||||
readability-identifier-naming.ClassCase: CamelCase
|
||||
readability-identifier-naming.ClassIgnoredRegexp: I.*
|
||||
readability-identifier-naming.ClassPrefix: C # We can't use regex here?!?!?!?
|
||||
readability-identifier-naming.EnumCase: CamelCase
|
||||
readability-identifier-naming.EnumPrefix: e
|
||||
readability-identifier-naming.EnumConstantCase: UPPER_CASE
|
||||
readability-identifier-naming.FunctionCase: camelBack
|
||||
readability-identifier-naming.NamespaceCase: CamelCase
|
||||
readability-identifier-naming.NamespacePrefix: N
|
||||
readability-identifier-naming.StructPrefix: S
|
||||
readability-identifier-naming.StructCase: CamelCase
|
19
.github/ISSUE_TEMPLATE/bug.yml
vendored
@@ -2,12 +2,13 @@ name: Bug Report
|
||||
description: Something is not working right
|
||||
labels: ["bug"]
|
||||
body:
|
||||
- type: markdown
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
value: |
|
||||
## Before opening a new issue, please take a moment to search through the current open and closed issues to check if it already exists.
|
||||
|
||||
---
|
||||
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
|
||||
@@ -28,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>
|
||||
|
||||
|
10
.github/actions/setup_base/action.yml
vendored
@@ -33,7 +33,9 @@ runs:
|
||||
libfontenc \
|
||||
libglvnd \
|
||||
libinput \
|
||||
libjxl \
|
||||
libliftoff \
|
||||
libwebp \
|
||||
libxcursor \
|
||||
libxcvt \
|
||||
libxfont2 \
|
||||
@@ -58,7 +60,8 @@ runs:
|
||||
xcb-util \
|
||||
xcb-util-image \
|
||||
libzip \
|
||||
librsvg
|
||||
librsvg \
|
||||
re2
|
||||
|
||||
- name: Get hyprwayland-scanner-git
|
||||
shell: bash
|
||||
@@ -69,6 +72,11 @@ runs:
|
||||
cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
|
||||
cmake --install build
|
||||
|
||||
- name: Get hyprgraphics-git
|
||||
shell: bash
|
||||
run: |
|
||||
git clone https://github.com/hyprwm/hyprgraphics && cd hyprgraphics && cmake -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:PATH=/usr -B build && cmake --build build --target hyprgraphics && cmake --install build
|
||||
|
||||
- name: Get hyprutils-git
|
||||
shell: bash
|
||||
run: |
|
||||
|
6
.github/pull_request_template.md
vendored
@@ -1,3 +1,9 @@
|
||||
<!--
|
||||
BEFORE you submit your PR, please check out the PR guidelines
|
||||
on our wiki: https://wiki.hyprland.org/Contributing-and-Debugging/PR-Guidelines/
|
||||
-->
|
||||
|
||||
|
||||
#### Describe your PR, what does it fix/add?
|
||||
|
||||
|
||||
|
2
.github/workflows/ci.yaml
vendored
@@ -39,7 +39,7 @@ jobs:
|
||||
tar -cvf Hyprland.tar.xz hyprland
|
||||
|
||||
- name: Release
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: Build archive
|
||||
path: Hyprland.tar.xz
|
||||
|
4
.github/workflows/man-update.yaml
vendored
@@ -17,14 +17,14 @@ jobs:
|
||||
run: sudo apt install pandoc
|
||||
|
||||
- name: Clone repository
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
token: ${{ secrets.PAT }}
|
||||
|
||||
- name: Build man pages
|
||||
run: make man
|
||||
|
||||
- uses: stefanzweifel/git-auto-commit-action@v4
|
||||
- uses: stefanzweifel/git-auto-commit-action@v5
|
||||
name: Commit
|
||||
with:
|
||||
commit_message: "[gha] build man pages"
|
||||
|
17
.github/workflows/nix-build.yml
vendored
@@ -1,3 +1,5 @@
|
||||
name: Nix (Build)
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
secrets:
|
||||
@@ -10,21 +12,18 @@ jobs:
|
||||
matrix:
|
||||
package:
|
||||
- hyprland
|
||||
# - hyprland-cross # cross compiling fails due to qt
|
||||
# failure chain: hyprland-qtutils -> qt6.qtsvg -> qt6.qtbase -> psqlodbc & qt6.qttranslations
|
||||
- xdg-desktop-portal-hyprland
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Clone repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.ref }}
|
||||
submodules: recursive
|
||||
|
||||
- uses: cachix/install-nix-action@v27
|
||||
- uses: DeterminateSystems/nix-installer-action@main
|
||||
- uses: DeterminateSystems/magic-nix-cache-action@main
|
||||
|
||||
- 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: (github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork) && !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
|
||||
|
7
.github/workflows/nix-update-inputs.yml
vendored
@@ -1,4 +1,4 @@
|
||||
name: Nix
|
||||
name: Nix (Update Inputs)
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
@@ -8,11 +8,12 @@ on:
|
||||
|
||||
jobs:
|
||||
update:
|
||||
if: github.repository == 'hyprwm/Hyprland'
|
||||
name: inputs
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Clone repository
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
token: ${{ secrets.PAT }}
|
||||
|
||||
@@ -21,6 +22,6 @@ jobs:
|
||||
run: nix/update-inputs.sh
|
||||
|
||||
- name: Commit
|
||||
uses: stefanzweifel/git-auto-commit-action@v4
|
||||
uses: stefanzweifel/git-auto-commit-action@v5
|
||||
with:
|
||||
commit_message: "[gha] Nix: update inputs"
|
||||
|
3
.github/workflows/release.yaml
vendored
@@ -11,7 +11,7 @@ jobs:
|
||||
steps:
|
||||
- name: Checkout Hyprland
|
||||
id: checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
@@ -20,7 +20,6 @@ jobs:
|
||||
run: |
|
||||
git fetch --unshallow || echo "failed unshallowing"
|
||||
bash -c scripts/generateVersion.sh
|
||||
mv scripts/generateVersion.sh scripts/generateVersion.sh.bak
|
||||
|
||||
- name: Create tarball with submodules
|
||||
id: tar
|
||||
|
2
.github/workflows/security-checks.yml
vendored
@@ -13,7 +13,7 @@ jobs:
|
||||
security-events: write
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Scan with Flawfinder
|
||||
uses: david-a-wheeler/flawfinder@8e4a779ad59dbfaee5da586aa9210853b701959c
|
||||
|
10
.github/workflows/stale.yml
vendored
@@ -7,22 +7,22 @@ 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
|
||||
pull-requests: write
|
||||
|
||||
steps:
|
||||
- uses: actions/stale@v5
|
||||
- uses: actions/stale@v9
|
||||
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
|
||||
|
6
.gitignore
vendored
@@ -14,6 +14,7 @@ _deps
|
||||
|
||||
build/
|
||||
result*
|
||||
/.pre-commit-config.yaml
|
||||
/.vscode/
|
||||
/.idea/
|
||||
.envrc
|
||||
@@ -37,3 +38,8 @@ gmon.out
|
||||
PKGBUILD
|
||||
|
||||
src/version.h
|
||||
hyprpm/Makefile
|
||||
hyprctl/Makefile
|
||||
|
||||
**/.#*.*
|
||||
**/#*.*#
|
||||
|
127
CMakeLists.txt
@@ -1,4 +1,4 @@
|
||||
cmake_minimum_required(VERSION 3.27)
|
||||
cmake_minimum_required(VERSION 3.30)
|
||||
|
||||
# Get version
|
||||
file(READ "${CMAKE_SOURCE_DIR}/VERSION" VER_RAW)
|
||||
@@ -15,6 +15,7 @@ include(GNUInstallDirs)
|
||||
set(HYPRLAND_VERSION ${VER})
|
||||
set(PREFIX ${CMAKE_INSTALL_PREFIX})
|
||||
set(INCLUDEDIR ${CMAKE_INSTALL_INCLUDEDIR})
|
||||
set(BINDIR ${CMAKE_INSTALL_BINDIR})
|
||||
configure_file(hyprland.pc.in hyprland.pc @ONLY)
|
||||
|
||||
set(CMAKE_MESSAGE_LOG_LEVEL "STATUS")
|
||||
@@ -25,8 +26,18 @@ message(STATUS "Gathering git info")
|
||||
execute_process(COMMAND ./scripts/generateVersion.sh
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
|
||||
|
||||
# udis
|
||||
add_subdirectory("subprojects/udis86")
|
||||
find_package(PkgConfig REQUIRED)
|
||||
|
||||
# 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)
|
||||
@@ -47,11 +58,11 @@ else()
|
||||
set(BUILDTYPE_LOWER "release")
|
||||
endif()
|
||||
|
||||
find_package(PkgConfig REQUIRED)
|
||||
|
||||
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")
|
||||
@@ -61,8 +72,11 @@ else()
|
||||
message(STATUS "Configuring Hyprland in Release with CMake")
|
||||
endif()
|
||||
|
||||
include_directories(. "src/" "subprojects/udis86/" "protocols/")
|
||||
set(CMAKE_CXX_STANDARD 23)
|
||||
add_compile_definitions(HYPRLAND_VERSION="${HYPRLAND_VERSION}")
|
||||
|
||||
include_directories(. "src/" "protocols/")
|
||||
|
||||
set(CMAKE_CXX_STANDARD 26)
|
||||
add_compile_options(
|
||||
-Wall
|
||||
-Wextra
|
||||
@@ -87,22 +101,25 @@ else()
|
||||
endif()
|
||||
find_package(OpenGL REQUIRED COMPONENTS ${GLES_VERSION})
|
||||
|
||||
pkg_check_modules(
|
||||
hyprctl_deps
|
||||
REQUIRED
|
||||
IMPORTED_TARGET
|
||||
hyprutils>=0.2.1)
|
||||
pkg_check_modules(aquamarine_dep REQUIRED IMPORTED_TARGET aquamarine>=0.4.5)
|
||||
pkg_check_modules(hyprlang_dep REQUIRED IMPORTED_TARGET hyprlang>=0.3.2)
|
||||
pkg_check_modules(hyprcursor_dep REQUIRED IMPORTED_TARGET hyprcursor>=0.1.7)
|
||||
pkg_check_modules(hyprutils_dep REQUIRED IMPORTED_TARGET hyprutils>=0.2.3)
|
||||
pkg_check_modules(hyprgraphics_dep REQUIRED IMPORTED_TARGET hyprgraphics>=0.1.1)
|
||||
|
||||
add_compile_definitions(AQUAMARINE_VERSION="${aquamarine_dep_VERSION}")
|
||||
add_compile_definitions(HYPRLANG_VERSION="${hyprlang_dep_VERSION}")
|
||||
add_compile_definitions(HYPRUTILS_VERSION="${hyprutils_dep_VERSION}")
|
||||
add_compile_definitions(HYPRCURSOR_VERSION="${hyprcursor_dep_VERSION}")
|
||||
add_compile_definitions(HYPRGRAPHICS_VERSION="${hyprgraphics_dep_VERSION}")
|
||||
|
||||
pkg_check_modules(
|
||||
deps
|
||||
REQUIRED
|
||||
IMPORTED_TARGET
|
||||
aquamarine
|
||||
xkbcommon
|
||||
uuid
|
||||
wayland-server
|
||||
wayland-client
|
||||
wayland-cursor
|
||||
wayland-server>=1.22.90
|
||||
wayland-protocols
|
||||
cairo
|
||||
pango
|
||||
@@ -111,15 +128,9 @@ pkg_check_modules(
|
||||
xcursor
|
||||
libdrm
|
||||
libinput
|
||||
hwdata
|
||||
libseat
|
||||
libdisplay-info
|
||||
libliftoff
|
||||
libudev
|
||||
gbm
|
||||
hyprlang>=0.3.2
|
||||
hyprcursor>=0.1.7
|
||||
hyprutils>=0.2.1)
|
||||
gio-2.0
|
||||
re2)
|
||||
|
||||
find_package(hyprwayland-scanner 0.3.10 REQUIRED)
|
||||
|
||||
@@ -201,14 +212,11 @@ else()
|
||||
REQUIRED
|
||||
IMPORTED_TARGET
|
||||
xcb
|
||||
xwayland
|
||||
xcb-util
|
||||
xcb-render
|
||||
xcb-xfixes
|
||||
xcb-icccm
|
||||
xcb-composite
|
||||
xcb-res
|
||||
xcb-ewmh
|
||||
xcb-errors)
|
||||
target_link_libraries(Hyprland PkgConfig::xdeps)
|
||||
endif()
|
||||
@@ -218,6 +226,15 @@ if(NO_SYSTEMD)
|
||||
else()
|
||||
message(STATUS "SYSTEMD support is requested (NO_SYSTEMD not defined)...")
|
||||
add_compile_definitions(USES_SYSTEMD)
|
||||
|
||||
# session file -uwsm
|
||||
if(NO_UWSM)
|
||||
message(STATUS "UWSM support is disabled...")
|
||||
else()
|
||||
message(STATUS "UWSM support is enabled (NO_UWSM not defined)...")
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/systemd/hyprland-uwsm.desktop
|
||||
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/wayland-sessions)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(CPACK_PROJECT_NAME ${PROJECT_NAME})
|
||||
@@ -231,14 +248,19 @@ target_precompile_headers(Hyprland PRIVATE
|
||||
|
||||
message(STATUS "Setting link libraries")
|
||||
|
||||
target_link_libraries(Hyprland rt PkgConfig::deps)
|
||||
target_link_libraries(Hyprland rt PkgConfig::aquamarine_dep PkgConfig::hyprlang_dep PkgConfig::hyprutils_dep PkgConfig::hyprcursor_dep PkgConfig::hyprgraphics_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(protocolnew protoPath protoName external)
|
||||
if(external)
|
||||
set(path ${CMAKE_SOURCE_DIR}/${protoPath})
|
||||
set(path ${protoPath})
|
||||
else()
|
||||
set(path ${WAYLAND_PROTOCOLS_DIR}/${protoPath})
|
||||
endif()
|
||||
@@ -257,22 +279,31 @@ 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/
|
||||
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)
|
||||
endfunction()
|
||||
|
||||
target_link_libraries(Hyprland OpenGL::EGL OpenGL::GL Threads::Threads
|
||||
libudis86 uuid)
|
||||
target_link_libraries(Hyprland OpenGL::EGL OpenGL::GL Threads::Threads)
|
||||
|
||||
protocolnew("subprojects/hyprland-protocols/protocols"
|
||||
"hyprland-global-shortcuts-v1" true)
|
||||
pkg_check_modules(hyprland_protocols_dep hyprland-protocols>=0.4.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("${HYPRLAND_PROTOCOLS}/protocols" "hyprland-global-shortcuts-v1"
|
||||
true)
|
||||
protocolnew("unstable/text-input" "text-input-unstable-v1" false)
|
||||
protocolnew("subprojects/hyprland-protocols/protocols"
|
||||
"hyprland-toplevel-export-v1" true)
|
||||
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)
|
||||
@@ -283,10 +314,11 @@ 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("${HYPRLAND_PROTOCOLS}/protocols" "hyprland-focus-grab-v1" true)
|
||||
protocolnew("protocols" "wlr-layer-shell-unstable-v1" true)
|
||||
protocolnew("protocols" "wayland-drm" true)
|
||||
protocolnew("${HYPRLAND_PROTOCOLS}/protocols" "hyprland-ctm-control-v1" 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)
|
||||
@@ -315,6 +347,9 @@ 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)
|
||||
protocolnew("staging/security-context" "security-context-v1" false)
|
||||
|
||||
protocolwayland()
|
||||
|
||||
@@ -329,19 +364,21 @@ install(
|
||||
CODE "execute_process( \
|
||||
COMMAND ${CMAKE_COMMAND} -E create_symlink \
|
||||
${CMAKE_INSTALL_FULL_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_DATAROOTDIR}/wayland-sessions)
|
||||
|
||||
# allow Hyprland to find wallpapers
|
||||
# allow Hyprland to find assets
|
||||
add_compile_definitions(DATAROOTDIR="${CMAKE_INSTALL_FULL_DATAROOTDIR}")
|
||||
|
||||
# wallpapers
|
||||
file(GLOB_RECURSE WALLPAPERS "assets/wall*")
|
||||
install(FILES ${WALLPAPERS} DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/hypr)
|
||||
# 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
|
||||
|
31
Makefile
@@ -1,28 +1,27 @@
|
||||
PREFIX = /usr/local
|
||||
|
||||
stub:
|
||||
@echo "Do not run $(MAKE) directly without any arguments. Please refer to the wiki on how to compile Hyprland."
|
||||
|
||||
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 ./build
|
||||
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 Debug --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
|
||||
@@ -87,8 +86,8 @@ asan:
|
||||
#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 ..
|
||||
|
@@ -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>
|
||||
|
||||
@@ -100,7 +100,7 @@ easy IPC, much more QoL stuff than other compositors and more...
|
||||
|
||||
<!----------------------------------------------------------------------------->
|
||||
|
||||
[Configure]: https://wiki.hyprland.org/Configuring/Configuring-Hyprland/
|
||||
[Configure]: https://wiki.hyprland.org/Configuring/
|
||||
[Stars]: https://starchart.cc/hyprwm/Hyprland
|
||||
[Hypr]: https://github.com/hyprwm/Hypr
|
||||
|
||||
@@ -125,7 +125,6 @@ easy IPC, much more QoL stuff than other 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'), 'hypr'), 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.
|
||||
|
@@ -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.
|
||||
|
@@ -3,7 +3,7 @@
|
||||
First of all, please remember to:
|
||||
- Check that your issue is not a duplicate
|
||||
- Read the [FAQ](https://wiki.hyprland.org/FAQ/)
|
||||
- Read the [Configuring Page](https://wiki.hyprland.org/Configuring/Configuring-Hyprland)
|
||||
- Read the [Configuring Page](https://wiki.hyprland.org/Configuring/)
|
||||
|
||||
<br/>
|
||||
|
||||
|
@@ -1,2 +1,2 @@
|
||||
install_man ('Hyprland.1')
|
||||
install_man ('hyprctl.1')
|
||||
install_man('Hyprland.1')
|
||||
install_man('hyprctl.1')
|
||||
|
@@ -1,6 +1,6 @@
|
||||
# This is an example Hyprland config file.
|
||||
# Refer to the wiki for more information.
|
||||
# https://wiki.hyprland.org/Configuring/Configuring-Hyprland/
|
||||
# https://wiki.hyprland.org/Configuring/
|
||||
|
||||
# Please note not all available settings / options are set here.
|
||||
# For a full list, see the wiki
|
||||
@@ -86,10 +86,12 @@ decoration {
|
||||
active_opacity = 1.0
|
||||
inactive_opacity = 1.0
|
||||
|
||||
drop_shadow = true
|
||||
shadow_range = 4
|
||||
shadow_render_power = 3
|
||||
col.shadow = rgba(1a1a1aee)
|
||||
shadow {
|
||||
enabled = true
|
||||
range = 4
|
||||
render_power = 3
|
||||
color = rgba(1a1a1aee)
|
||||
}
|
||||
|
||||
# https://wiki.hyprland.org/Configuring/Variables/#blur
|
||||
blur {
|
||||
@@ -103,20 +105,44 @@ decoration {
|
||||
|
||||
# https://wiki.hyprland.org/Configuring/Variables/#animations
|
||||
animations {
|
||||
enabled = true
|
||||
enabled = yes, please :)
|
||||
|
||||
# Default animations, see https://wiki.hyprland.org/Configuring/Animations/ for more
|
||||
|
||||
bezier = myBezier, 0.05, 0.9, 0.1, 1.05
|
||||
bezier = easeOutQuint,0.23,1,0.32,1
|
||||
bezier = easeInOutCubic,0.65,0.05,0.36,1
|
||||
bezier = linear,0,0,1,1
|
||||
bezier = almostLinear,0.5,0.5,0.75,1.0
|
||||
bezier = quick,0.15,0,0.1,1
|
||||
|
||||
animation = windows, 1, 7, myBezier
|
||||
animation = windowsOut, 1, 7, default, popin 80%
|
||||
animation = border, 1, 10, default
|
||||
animation = borderangle, 1, 8, default
|
||||
animation = fade, 1, 7, default
|
||||
animation = workspaces, 1, 6, default
|
||||
animation = global, 1, 10, default
|
||||
animation = border, 1, 5.39, easeOutQuint
|
||||
animation = windows, 1, 4.79, easeOutQuint
|
||||
animation = windowsIn, 1, 4.1, easeOutQuint, popin 87%
|
||||
animation = windowsOut, 1, 1.49, linear, popin 87%
|
||||
animation = fadeIn, 1, 1.73, almostLinear
|
||||
animation = fadeOut, 1, 1.46, almostLinear
|
||||
animation = fade, 1, 3.03, quick
|
||||
animation = layers, 1, 3.81, easeOutQuint
|
||||
animation = layersIn, 1, 4, easeOutQuint, fade
|
||||
animation = layersOut, 1, 1.5, linear, fade
|
||||
animation = fadeLayersIn, 1, 1.79, almostLinear
|
||||
animation = fadeLayersOut, 1, 1.39, almostLinear
|
||||
animation = workspaces, 1, 1.94, almostLinear, fade
|
||||
animation = workspacesIn, 1, 1.21, almostLinear, fade
|
||||
animation = workspacesOut, 1, 1.94, almostLinear, fade
|
||||
}
|
||||
|
||||
# Ref https://wiki.hyprland.org/Configuring/Workspace-Rules/
|
||||
# "Smart gaps" / "No gaps when only"
|
||||
# uncomment all if you wish to use that.
|
||||
# workspace = w[tv1], gapsout:0, gapsin:0
|
||||
# workspace = f[1], gapsout:0, gapsin:0
|
||||
# windowrulev2 = bordersize 0, floating:0, onworkspace:w[tv1]
|
||||
# windowrulev2 = rounding 0, floating:0, onworkspace:w[tv1]
|
||||
# windowrulev2 = bordersize 0, floating:0, onworkspace:f[1]
|
||||
# windowrulev2 = rounding 0, floating:0, onworkspace:f[1]
|
||||
|
||||
# See https://wiki.hyprland.org/Configuring/Dwindle-Layout/ for more
|
||||
dwindle {
|
||||
pseudotile = true # Master switch for pseudotiling. Enabling is bound to mainMod + P in the keybinds section below
|
||||
@@ -169,9 +195,9 @@ device {
|
||||
}
|
||||
|
||||
|
||||
####################
|
||||
### KEYBINDINGSS ###
|
||||
####################
|
||||
###################
|
||||
### KEYBINDINGS ###
|
||||
###################
|
||||
|
||||
# See https://wiki.hyprland.org/Configuring/Keywords/
|
||||
$mainMod = SUPER # Sets "Windows" key as main modifier
|
||||
@@ -228,6 +254,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 +281,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
|
||||
|
@@ -3,3 +3,5 @@ Name=Hyprland
|
||||
Comment=An intelligent dynamic tiling Wayland compositor
|
||||
Exec=Hyprland
|
||||
Type=Application
|
||||
DesktopNames=Hyprland
|
||||
Keywords=tiling;wayland;compositor;
|
||||
|
@@ -1,2 +1,10 @@
|
||||
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')
|
||||
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',
|
||||
)
|
||||
|
194
flake.lock
generated
@@ -16,11 +16,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1722347739,
|
||||
"narHash": "sha256-rAoh+K6KG+b1DwSWtqRVocdojnH6nGk6q07mNltoUSM=",
|
||||
"lastModified": 1734364797,
|
||||
"narHash": "sha256-2h1c+P0v3l0Z/ypUSsAPhU/yiSRgFwjVFODWp0S3d/w=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "aquamarine",
|
||||
"rev": "7c3565f9bedc7cb601cc0baa14792247e4dc1d5a",
|
||||
"rev": "8e77618b403a82fde2105a8e3cd7cabe7ef00952",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -29,6 +29,43 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-compat": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1696426674,
|
||||
"narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=",
|
||||
"owner": "edolstra",
|
||||
"repo": "flake-compat",
|
||||
"rev": "0f9255e01c2351cc7d116c072cb317785dd33b33",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "edolstra",
|
||||
"repo": "flake-compat",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"gitignore": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"pre-commit-hooks",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1709087332,
|
||||
"narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=",
|
||||
"owner": "hercules-ci",
|
||||
"repo": "gitignore.nix",
|
||||
"rev": "637db329424fd7e46cf4185293b9cc8c88c95394",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "hercules-ci",
|
||||
"repo": "gitignore.nix",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"hyprcursor": {
|
||||
"inputs": {
|
||||
"hyprlang": [
|
||||
@@ -42,11 +79,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1721330371,
|
||||
"narHash": "sha256-aYlHTWylczLt6ERJyg6E66Y/XSCbVL7leVcRuJmVbpI=",
|
||||
"lastModified": 1734364709,
|
||||
"narHash": "sha256-+2bZJL2u5hva7rSp65OfKJBK+k03T6GB/NCvpoS1OOo=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "hyprcursor",
|
||||
"rev": "4493a972b48f9c3014befbbf381ed5fff91a65dc",
|
||||
"rev": "f388aacd22be4a6e4d634fbaf6f75eb0713d239a",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -55,23 +92,47 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"hyprland-protocols": {
|
||||
"hyprgraphics": {
|
||||
"inputs": {
|
||||
"hyprutils": [
|
||||
"hyprutils"
|
||||
],
|
||||
"nixpkgs": [
|
||||
"xdph",
|
||||
"nixpkgs"
|
||||
],
|
||||
"systems": [
|
||||
"xdph",
|
||||
"systems"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1721326555,
|
||||
"narHash": "sha256-zCu4R0CSHEactW9JqYki26gy8h9f6rHmSwj4XJmlHgg=",
|
||||
"lastModified": 1733684019,
|
||||
"narHash": "sha256-2kYREgmSmbLsmDpLEq96hxVAU3qz8aCvVhF65yCFZHY=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "hyprgraphics",
|
||||
"rev": "fb2c0268645a77403af3b8a4ce8fa7ba5917f15d",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "hyprwm",
|
||||
"repo": "hyprgraphics",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"hyprland-protocols": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
],
|
||||
"systems": [
|
||||
"systems"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1728345020,
|
||||
"narHash": "sha256-xGbkc7U/Roe0/Cv3iKlzijIaFBNguasI31ynL2IlEoM=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "hyprland-protocols",
|
||||
"rev": "5a11232266bf1a1f5952d5b179c3f4b2facaaa84",
|
||||
"rev": "a7c183800e74f337753de186522b9017a07a8cee",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -80,6 +141,32 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"hyprland-qtutils": {
|
||||
"inputs": {
|
||||
"hyprutils": [
|
||||
"hyprutils"
|
||||
],
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
],
|
||||
"systems": [
|
||||
"systems"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1733940128,
|
||||
"narHash": "sha256-hmfXWj2GA9cj1QUkPFYtAAeohhs615zL4E3APy3FnvQ=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "hyprland-qtutils",
|
||||
"rev": "3833097e50473a152dd614d4b468886840b4ea78",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "hyprwm",
|
||||
"repo": "hyprland-qtutils",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"hyprlang": {
|
||||
"inputs": {
|
||||
"hyprutils": [
|
||||
@@ -93,11 +180,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1721324361,
|
||||
"narHash": "sha256-BiJKO0IIdnSwHQBSrEJlKlFr753urkLE48wtt0UhNG4=",
|
||||
"lastModified": 1734364628,
|
||||
"narHash": "sha256-ii8fzJfI953n/EmIxVvq64ZAwhvwuuPHWfGd61/mJG8=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "hyprlang",
|
||||
"rev": "adbefbf49664a6c2c8bf36b6487fd31e3eb68086",
|
||||
"rev": "16e59c1eb13d9fb6de066f54e7555eb5e8a4aba5",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -116,11 +203,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1722098849,
|
||||
"narHash": "sha256-D3wIZlBNh7LuZ0NaoCpY/Pvu+xHxIVtSN+KkWZYvvVs=",
|
||||
"lastModified": 1733502241,
|
||||
"narHash": "sha256-KAUNC4Dgq8WQjYov5auBw/usaHixhacvb7cRDd0AG/k=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "hyprutils",
|
||||
"rev": "5dcbbc1e3de40b2cecfd2007434d86e924468f1f",
|
||||
"rev": "104117aed6dd68561be38b50f218190aa47f2cd8",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -139,11 +226,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1721324119,
|
||||
"narHash": "sha256-SOOqIT27/X792+vsLSeFdrNTF+OSRp5qXv6Te+fb2Qg=",
|
||||
"lastModified": 1726874836,
|
||||
"narHash": "sha256-VKR0sf0PSNCB0wPHVKSAn41mCNVCnegWmgkrneKDhHM=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "hyprwayland-scanner",
|
||||
"rev": "a048a6cb015340bd82f97c1f40a4b595ca85cc30",
|
||||
"rev": "500c81a9e1a76760371049a8d99e008ea77aa59e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -154,11 +241,11 @@
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1722185531,
|
||||
"narHash": "sha256-veKR07psFoJjINLC8RK4DiLniGGMgF3QMlS4tb74S6k=",
|
||||
"lastModified": 1734119587,
|
||||
"narHash": "sha256-AKU6qqskl0yf2+JdRdD0cfxX4b9x3KKV5RqA6wijmPM=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "52ec9ac3b12395ad677e8b62106f0b98c1f8569d",
|
||||
"rev": "3566ab7246670a43abd2ffa913cc62dad9cdf7d5",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -168,14 +255,57 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs-stable": {
|
||||
"locked": {
|
||||
"lastModified": 1730741070,
|
||||
"narHash": "sha256-edm8WG19kWozJ/GqyYx2VjW99EdhjKwbY3ZwdlPAAlo=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "d063c1dd113c91ab27959ba540c0d9753409edf3",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixos-24.05",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"pre-commit-hooks": {
|
||||
"inputs": {
|
||||
"flake-compat": "flake-compat",
|
||||
"gitignore": "gitignore",
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
],
|
||||
"nixpkgs-stable": "nixpkgs-stable"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1734279981,
|
||||
"narHash": "sha256-NdaCraHPp8iYMWzdXAt5Nv6sA3MUzlCiGiR586TCwo0=",
|
||||
"owner": "cachix",
|
||||
"repo": "git-hooks.nix",
|
||||
"rev": "aa9f40c906904ebd83da78e7f328cd8aeaeae785",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "cachix",
|
||||
"repo": "git-hooks.nix",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"aquamarine": "aquamarine",
|
||||
"hyprcursor": "hyprcursor",
|
||||
"hyprgraphics": "hyprgraphics",
|
||||
"hyprland-protocols": "hyprland-protocols",
|
||||
"hyprland-qtutils": "hyprland-qtutils",
|
||||
"hyprlang": "hyprlang",
|
||||
"hyprutils": "hyprutils",
|
||||
"hyprwayland-scanner": "hyprwayland-scanner",
|
||||
"nixpkgs": "nixpkgs",
|
||||
"pre-commit-hooks": "pre-commit-hooks",
|
||||
"systems": "systems",
|
||||
"xdph": "xdph"
|
||||
}
|
||||
@@ -197,10 +327,18 @@
|
||||
},
|
||||
"xdph": {
|
||||
"inputs": {
|
||||
"hyprland-protocols": "hyprland-protocols",
|
||||
"hyprland-protocols": [
|
||||
"hyprland-protocols"
|
||||
],
|
||||
"hyprlang": [
|
||||
"hyprlang"
|
||||
],
|
||||
"hyprutils": [
|
||||
"hyprutils"
|
||||
],
|
||||
"hyprwayland-scanner": [
|
||||
"hyprwayland-scanner"
|
||||
],
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
],
|
||||
@@ -209,11 +347,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1722365976,
|
||||
"narHash": "sha256-Khdm+mDzYA//XaU0M+hftod+rKr5q9SSHSEuiQ0/9ow=",
|
||||
"lastModified": 1734124279,
|
||||
"narHash": "sha256-YNpFfiQjYt2o6LGcMN9NkjVvprC8ELrIpLHlbZbclRM=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "xdg-desktop-portal-hyprland",
|
||||
"rev": "7f2a77ddf60390248e2a3de2261d7102a13e5341",
|
||||
"rev": "0c6861f819f6d31f6195c9864709b2556f00b5cf",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
61
flake.nix
@@ -22,6 +22,26 @@
|
||||
inputs.hyprlang.follows = "hyprlang";
|
||||
};
|
||||
|
||||
hyprgraphics = {
|
||||
url = "github:hyprwm/hyprgraphics";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
inputs.systems.follows = "systems";
|
||||
inputs.hyprutils.follows = "hyprutils";
|
||||
};
|
||||
|
||||
hyprland-protocols = {
|
||||
url = "github:hyprwm/hyprland-protocols";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
inputs.systems.follows = "systems";
|
||||
};
|
||||
|
||||
hyprland-qtutils = {
|
||||
url = "github:hyprwm/hyprland-qtutils";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
inputs.systems.follows = "systems";
|
||||
inputs.hyprutils.follows = "hyprutils";
|
||||
};
|
||||
|
||||
hyprlang = {
|
||||
url = "github:hyprwm/hyprlang";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
@@ -45,7 +65,15 @@
|
||||
url = "github:hyprwm/xdg-desktop-portal-hyprland";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
inputs.systems.follows = "systems";
|
||||
inputs.hyprland-protocols.follows = "hyprland-protocols";
|
||||
inputs.hyprlang.follows = "hyprlang";
|
||||
inputs.hyprutils.follows = "hyprutils";
|
||||
inputs.hyprwayland-scanner.follows = "hyprwayland-scanner";
|
||||
};
|
||||
|
||||
pre-commit-hooks = {
|
||||
url = "github:cachix/git-hooks.nix";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
};
|
||||
|
||||
@@ -65,6 +93,15 @@
|
||||
hyprland-extras
|
||||
];
|
||||
});
|
||||
pkgsCrossFor = eachSystem (system: crossSystem:
|
||||
import nixpkgs {
|
||||
localSystem = system;
|
||||
inherit crossSystem;
|
||||
overlays = with self.overlays; [
|
||||
hyprland-packages
|
||||
hyprland-extras
|
||||
];
|
||||
});
|
||||
in {
|
||||
overlays = import ./nix/overlays.nix {inherit self lib inputs;};
|
||||
|
||||
@@ -74,6 +111,18 @@
|
||||
self.packages.${system})
|
||||
// {
|
||||
inherit (self.packages.${system}) xdg-desktop-portal-hyprland;
|
||||
pre-commit-check = inputs.pre-commit-hooks.lib.${system}.run {
|
||||
src = ./.;
|
||||
hooks = {
|
||||
hyprland-treewide-formatter = {
|
||||
enable = true;
|
||||
entry = "${self.formatter.${system}}/bin/hyprland-treewide-formatter";
|
||||
pass_filenames = false;
|
||||
excludes = ["subprojects"];
|
||||
always_run = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
});
|
||||
|
||||
packages = eachSystem (system: {
|
||||
@@ -81,34 +130,30 @@
|
||||
inherit
|
||||
(pkgsFor.${system})
|
||||
# hyprland-packages
|
||||
|
||||
hyprland
|
||||
hyprland-debug
|
||||
hyprland-legacy-renderer
|
||||
hyprland-unwrapped
|
||||
# hyprland-extras
|
||||
|
||||
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];
|
||||
inherit (self.checks.${system}.pre-commit-check) shellHook;
|
||||
};
|
||||
});
|
||||
|
||||
formatter = eachSystem (system: nixpkgs.legacyPackages.${system}.alejandra);
|
||||
formatter = eachSystem (system: pkgsFor.${system}.callPackage ./nix/formatter.nix {});
|
||||
|
||||
nixosModules.default = import ./nix/module.nix inputs;
|
||||
homeManagerModules.default = import ./nix/hm-module.nix self;
|
||||
|
@@ -5,7 +5,7 @@ project(
|
||||
DESCRIPTION "Control utility for Hyprland"
|
||||
)
|
||||
|
||||
pkg_check_modules(deps REQUIRED IMPORTED_TARGET hyprutils>=0.1.1)
|
||||
pkg_check_modules(hyprctl_deps REQUIRED IMPORTED_TARGET hyprutils>=0.2.4 re2)
|
||||
|
||||
add_executable(hyprctl "main.cpp")
|
||||
|
||||
|
@@ -1,4 +0,0 @@
|
||||
all:
|
||||
$(CXX) $(CXXFLAGS) -std=c++2b ./main.cpp -o ./hyprctl
|
||||
clean:
|
||||
rm ./hyprctl
|
@@ -1,5 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <string_view>
|
||||
|
||||
const std::string_view USAGE = R"#(usage: hyprctl [flags] <command> [args...|--help]
|
||||
|
||||
commands:
|
||||
|
@@ -1,17 +1,17 @@
|
||||
_hyprctl_cmd_2 () {
|
||||
_hyprctl_cmd_1 () {
|
||||
hyprctl monitors | awk '/Monitor/{ print $2 }'
|
||||
}
|
||||
|
||||
_hyprctl_cmd_3 () {
|
||||
hyprpm list | awk '/Plugin/{ 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 | awk '/class/{ 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 | awk '/Monitor/{ print $2 }'
|
||||
end
|
||||
|
||||
function _hyprctl_4
|
||||
set 1 $argv[1]
|
||||
hyprpm list | awk '/Plugin/{ 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 | awk '/class/{ 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,6 +9,7 @@ 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 | awk '/class/{print $2}' }}};
|
||||
@@ -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,145 +1,160 @@
|
||||
#compdef hyprctl
|
||||
|
||||
_hyprctl_cmd_2 () {
|
||||
_hyprctl_cmd_1 () {
|
||||
hyprctl monitors | awk '/Monitor/{ print $2 }'
|
||||
}
|
||||
|
||||
_hyprctl_cmd_3 () {
|
||||
hyprpm list | awk '/Plugin/{ print $4 }'
|
||||
hyprctl clients | awk '/class/{print $2}'
|
||||
}
|
||||
|
||||
_hyprctl_cmd_0 () {
|
||||
hyprctl clients | awk '/class/{ 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
|
||||
|
||||
@@ -199,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]}
|
||||
@@ -252,4 +267,8 @@ _hyprctl () {
|
||||
return 0
|
||||
}
|
||||
|
||||
compdef _hyprctl hyprctl
|
||||
if [[ $ZSH_EVAL_CONTEXT =~ :file$ ]]; then
|
||||
compdef _hyprctl hyprctl
|
||||
else
|
||||
_hyprctl
|
||||
fi
|
||||
|
@@ -1,3 +1,5 @@
|
||||
#include <re2/re2.h>
|
||||
|
||||
#include <cctype>
|
||||
#include <netdb.h>
|
||||
#include <netinet/in.h>
|
||||
@@ -17,15 +19,15 @@
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <print>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <deque>
|
||||
#include <filesystem>
|
||||
#include <cstdarg>
|
||||
#include <regex>
|
||||
#include <sys/socket.h>
|
||||
#include <hyprutils/string/String.hpp>
|
||||
#include <cstring>
|
||||
using namespace Hyprutils::String;
|
||||
|
||||
#include "Strings.hpp"
|
||||
@@ -43,18 +45,24 @@ struct SInstanceData {
|
||||
bool valid = true;
|
||||
};
|
||||
|
||||
void log(std::string str) {
|
||||
void log(const std::string& str) {
|
||||
if (quiet)
|
||||
return;
|
||||
|
||||
std::cout << str << "\n";
|
||||
std::println("{}", str);
|
||||
}
|
||||
|
||||
static int getUID() {
|
||||
const auto UID = getuid();
|
||||
const auto PWUID = getpwuid(UID);
|
||||
return PWUID ? PWUID->pw_uid : UID;
|
||||
}
|
||||
|
||||
std::string getRuntimeDir() {
|
||||
const auto XDG = getenv("XDG_RUNTIME_DIR");
|
||||
|
||||
if (!XDG) {
|
||||
const std::string USERID = std::to_string(getpwuid(getuid())->pw_uid);
|
||||
const std::string USERID = std::to_string(getUID());
|
||||
return "/run/user/" + USERID + "/hypr";
|
||||
}
|
||||
|
||||
@@ -64,6 +72,11 @@ std::string getRuntimeDir() {
|
||||
std::vector<SInstanceData> instances() {
|
||||
std::vector<SInstanceData> result;
|
||||
|
||||
try {
|
||||
if (!std::filesystem::exists(getRuntimeDir()))
|
||||
return {};
|
||||
} catch (std::exception& e) { return {}; }
|
||||
|
||||
for (const auto& el : std::filesystem::directory_iterator(getRuntimeDir())) {
|
||||
if (!el.is_directory() || !std::filesystem::exists(el.path().string() + "/hyprland.lock"))
|
||||
continue;
|
||||
@@ -104,7 +117,7 @@ std::vector<SInstanceData> instances() {
|
||||
static volatile bool sigintReceived = false;
|
||||
void intHandler(int sig) {
|
||||
sigintReceived = true;
|
||||
std::cout << "[hyprctl] SIGINT received, closing connection" << std::endl;
|
||||
std::println("[hyprctl] SIGINT received, closing connection");
|
||||
}
|
||||
|
||||
int rollingRead(const int socket) {
|
||||
@@ -113,13 +126,13 @@ int rollingRead(const int socket) {
|
||||
|
||||
constexpr size_t BUFFER_SIZE = 8192;
|
||||
std::array<char, BUFFER_SIZE> buffer = {0};
|
||||
int sizeWritten = 0;
|
||||
std::cout << "[hyprctl] reading from socket following up log:" << std::endl;
|
||||
long sizeWritten = 0;
|
||||
std::println("[hyprctl] reading from socket following up log:");
|
||||
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;
|
||||
std::println("Couldn't read (5): {}: {}", strerror(errno), errno);
|
||||
close(socket);
|
||||
return 5;
|
||||
}
|
||||
@@ -128,7 +141,7 @@ int rollingRead(const int socket) {
|
||||
break;
|
||||
|
||||
if (sizeWritten > 0) {
|
||||
std::cout << std::string(buffer.data(), sizeWritten);
|
||||
std::println("{}", std::string(buffer.data(), sizeWritten));
|
||||
buffer.fill('\0');
|
||||
}
|
||||
|
||||
@@ -161,7 +174,7 @@ int request(std::string arg, int minArgs = 0, bool needRoll = false) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
const std::string USERID = std::to_string(getpwuid(getuid())->pw_uid);
|
||||
const std::string USERID = std::to_string(getUID());
|
||||
|
||||
sockaddr_un serverAddress = {0};
|
||||
serverAddress.sun_family = AF_UNIX;
|
||||
@@ -231,7 +244,7 @@ int requestHyprpaper(std::string arg) {
|
||||
sockaddr_un serverAddress = {0};
|
||||
serverAddress.sun_family = AF_UNIX;
|
||||
|
||||
const std::string USERID = std::to_string(getpwuid(getuid())->pw_uid);
|
||||
const std::string USERID = std::to_string(getUID());
|
||||
|
||||
std::string socketPath = getRuntimeDir() + "/" + instanceSignature + "/.hyprpaper.sock";
|
||||
|
||||
@@ -269,11 +282,10 @@ int requestHyprpaper(std::string arg) {
|
||||
}
|
||||
|
||||
void batchRequest(std::string arg, bool json) {
|
||||
std::string commands = arg.substr(arg.find_first_of(" ") + 1);
|
||||
std::string commands = arg.substr(arg.find_first_of(' ') + 1);
|
||||
|
||||
if (json) {
|
||||
commands = "j/" + std::regex_replace(commands, std::regex(";\\s*"), ";j/");
|
||||
}
|
||||
if (json)
|
||||
RE2::GlobalReplace(&commands, ";\\s*", ";j/");
|
||||
|
||||
std::string rq = "[[BATCH]]" + commands;
|
||||
request(rq);
|
||||
@@ -286,12 +298,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": "{}",
|
||||
@@ -309,11 +321,11 @@ void instancesRequest(bool json) {
|
||||
log(result + "\n");
|
||||
}
|
||||
|
||||
std::deque<std::string> splitArgs(int argc, char** argv) {
|
||||
std::deque<std::string> result;
|
||||
std::vector<std::string> splitArgs(int argc, char** argv) {
|
||||
std::vector<std::string> result;
|
||||
|
||||
for (auto i = 1 /* skip the executable */; i < argc; ++i)
|
||||
result.push_back(std::string(argv[i]));
|
||||
result.emplace_back(argv[i]);
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -322,7 +334,7 @@ int main(int argc, char** argv) {
|
||||
bool parseArgs = true;
|
||||
|
||||
if (argc < 2) {
|
||||
std::cout << USAGE << std::endl;
|
||||
std::println("{}", USAGE);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -359,7 +371,7 @@ int main(int argc, char** argv) {
|
||||
++i;
|
||||
|
||||
if (i >= ARGS.size()) {
|
||||
std::cout << USAGE << std::endl;
|
||||
std::println("{}", USAGE);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -370,24 +382,24 @@ int main(int argc, char** argv) {
|
||||
const std::string& cmd = ARGS[0];
|
||||
|
||||
if (cmd == "hyprpaper") {
|
||||
std::cout << HYPRPAPER_HELP << std::endl;
|
||||
std::println("{}", HYPRPAPER_HELP);
|
||||
} else if (cmd == "notify") {
|
||||
std::cout << NOTIFY_HELP << std::endl;
|
||||
std::println("{}", NOTIFY_HELP);
|
||||
} else if (cmd == "output") {
|
||||
std::cout << OUTPUT_HELP << std::endl;
|
||||
std::println("{}", OUTPUT_HELP);
|
||||
} else if (cmd == "plugin") {
|
||||
std::cout << PLUGIN_HELP << std::endl;
|
||||
std::println("{}", PLUGIN_HELP);
|
||||
} else if (cmd == "setprop") {
|
||||
std::cout << SETPROP_HELP << std::endl;
|
||||
std::println("{}", SETPROP_HELP);
|
||||
} else if (cmd == "switchxkblayout") {
|
||||
std::cout << SWITCHXKBLAYOUT_HELP << std::endl;
|
||||
std::println("{}", SWITCHXKBLAYOUT_HELP);
|
||||
} else {
|
||||
std::cout << USAGE << std::endl;
|
||||
std::println("{}", USAGE);
|
||||
}
|
||||
|
||||
return 1;
|
||||
} else {
|
||||
std::cout << USAGE << std::endl;
|
||||
std::println("{}", USAGE);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -398,7 +410,7 @@ int main(int argc, char** argv) {
|
||||
}
|
||||
|
||||
if (fullRequest.empty()) {
|
||||
std::cout << USAGE << std::endl;
|
||||
std::println("{}", USAGE);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -475,7 +487,7 @@ int main(int argc, char** argv) {
|
||||
else if (fullRequest.contains("/decorations"))
|
||||
exitStatus = request(fullRequest, 1);
|
||||
else if (fullRequest.contains("/--help"))
|
||||
std::cout << USAGE << std::endl;
|
||||
std::println("{}", USAGE);
|
||||
else if (fullRequest.contains("/rollinglog") && needRoll)
|
||||
exitStatus = request(fullRequest, 0, true);
|
||||
else {
|
||||
|
@@ -1,10 +1,27 @@
|
||||
executable('hyprctl', 'main.cpp',
|
||||
executable(
|
||||
'hyprctl',
|
||||
'main.cpp',
|
||||
dependencies: [
|
||||
dependency('hyprutils', version: '>= 0.1.1'),
|
||||
dependency('re2', required: true)
|
||||
],
|
||||
install: true
|
||||
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',
|
||||
)
|
||||
|
@@ -9,11 +9,11 @@ file(GLOB_RECURSE SRCFILES CONFIGURE_DEPENDS "src/*.cpp")
|
||||
|
||||
set(CMAKE_CXX_STANDARD 23)
|
||||
|
||||
pkg_check_modules(deps REQUIRED IMPORTED_TARGET tomlplusplus hyprutils>=0.1.1)
|
||||
pkg_check_modules(hyprpm_deps REQUIRED IMPORTED_TARGET tomlplusplus hyprutils>=0.2.4)
|
||||
|
||||
add_executable(hyprpm ${SRCFILES})
|
||||
|
||||
target_link_libraries(hyprpm PUBLIC PkgConfig::deps)
|
||||
target_link_libraries(hyprpm PUBLIC PkgConfig::hyprpm_deps)
|
||||
|
||||
# binary
|
||||
install(TARGETS hyprpm)
|
||||
|
@@ -2,6 +2,10 @@ _hyprpm_cmd_0 () {
|
||||
hyprpm list | awk '/Plugin/{print $4}'
|
||||
}
|
||||
|
||||
_hyprpm_cmd_1 () {
|
||||
hyprpm list | awk '/Repository/{print $4}' | sed 's/:$//'
|
||||
}
|
||||
|
||||
_hyprpm () {
|
||||
if [[ $(type -t _get_comp_words_by_ref) != function ]]; then
|
||||
echo _get_comp_words_by_ref: function not defined. Make sure the bash-completions system package is installed
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
@@ -3,6 +3,11 @@ function _hyprpm_1
|
||||
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
|
||||
set COMP_LINE (commandline --cut-at-cursor)
|
||||
|
||||
@@ -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"
|
||||
@@ -17,3 +18,4 @@ hyprpm [<FLAGS>]... <ARGUMENT>
|
||||
;
|
||||
|
||||
<PLUGINS> ::= {{{ hyprpm list | awk '/Plugin/{print $4}' }}};
|
||||
<PLUGIN_REPOS> ::= {{{ hyprpm list | awk '/Repository/{print $4}' | sed 's/:$//' }}};
|
||||
|
@@ -4,34 +4,40 @@ _hyprpm_cmd_0 () {
|
||||
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]}
|
||||
|
@@ -1,6 +1,6 @@
|
||||
#include "DataState.hpp"
|
||||
#include <toml++/toml.hpp>
|
||||
#include <iostream>
|
||||
#include <print>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include "PluginManager.hpp"
|
||||
@@ -8,7 +8,7 @@
|
||||
std::string DataState::getDataStatePath() {
|
||||
const auto HOME = getenv("HOME");
|
||||
if (!HOME) {
|
||||
std::cerr << "DataState: no $HOME\n";
|
||||
std::println(stderr, "DataState: no $HOME");
|
||||
throw std::runtime_error("no $HOME");
|
||||
return "";
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
|
@@ -1,12 +1,15 @@
|
||||
#include "PluginManager.hpp"
|
||||
#include "../helpers/Colors.hpp"
|
||||
#include "../helpers/StringUtils.hpp"
|
||||
#include "../progress/CProgressBar.hpp"
|
||||
#include "Manifest.hpp"
|
||||
#include "DataState.hpp"
|
||||
|
||||
#include <cstdio>
|
||||
#include <iostream>
|
||||
#include <array>
|
||||
#include <filesystem>
|
||||
#include <print>
|
||||
#include <thread>
|
||||
#include <fstream>
|
||||
#include <algorithm>
|
||||
@@ -20,37 +23,56 @@
|
||||
#include <toml++/toml.hpp>
|
||||
|
||||
#include <hyprutils/string/String.hpp>
|
||||
#include <hyprutils/os/Process.hpp>
|
||||
using namespace Hyprutils::String;
|
||||
using namespace Hyprutils::OS;
|
||||
|
||||
static std::string execAndGet(std::string cmd) {
|
||||
cmd += " 2>&1";
|
||||
std::array<char, 128> buffer;
|
||||
std::string result;
|
||||
using PcloseType = int (*)(FILE*);
|
||||
const std::unique_ptr<FILE, PcloseType> pipe(popen(cmd.c_str(), "r"), static_cast<PcloseType>(pclose));
|
||||
if (!pipe)
|
||||
return "";
|
||||
|
||||
while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) {
|
||||
result += buffer.data();
|
||||
}
|
||||
return result;
|
||||
CProcess proc("/bin/sh", {"-c", cmd});
|
||||
|
||||
if (!proc.runSync())
|
||||
return "error";
|
||||
|
||||
return proc.stdOut();
|
||||
}
|
||||
|
||||
SHyprlandVersion CPluginManager::getHyprlandVersion() {
|
||||
static SHyprlandVersion ver;
|
||||
static bool once = false;
|
||||
static std::string getTempRoot() {
|
||||
static auto ENV = getenv("XDG_RUNTIME_DIR");
|
||||
if (!ENV) {
|
||||
std::cerr << "\nERROR: XDG_RUNTIME_DIR not set!\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (once)
|
||||
return ver;
|
||||
const auto STR = ENV + std::string{"/hyprpm/"};
|
||||
|
||||
once = true;
|
||||
const auto HLVERCALL = execAndGet("hyprctl version");
|
||||
return STR;
|
||||
}
|
||||
|
||||
SHyprlandVersion CPluginManager::getHyprlandVersion(bool running) {
|
||||
static bool onceRunning = false;
|
||||
static bool onceInstalled = false;
|
||||
static SHyprlandVersion verRunning;
|
||||
static SHyprlandVersion verInstalled;
|
||||
|
||||
if (onceRunning && running)
|
||||
return verRunning;
|
||||
|
||||
if (onceInstalled && !running)
|
||||
return verInstalled;
|
||||
|
||||
if (running)
|
||||
onceRunning = true;
|
||||
else
|
||||
onceInstalled = true;
|
||||
|
||||
const auto HLVERCALL = running ? execAndGet("hyprctl version") : execAndGet("Hyprland --version");
|
||||
if (m_bVerbose)
|
||||
std::cout << Colors::BLUE << "[v] " << Colors::RESET << "version returned: " << HLVERCALL << "\n";
|
||||
std::println("{}", verboseString("{} version returned: {}", running ? "running" : "installed", HLVERCALL));
|
||||
|
||||
if (!HLVERCALL.contains("Tag:")) {
|
||||
std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " You don't seem to be running Hyprland.";
|
||||
std::println(stderr, "\n{}", failureString("You don't seem to be running Hyprland."));
|
||||
return SHyprlandVersion{};
|
||||
}
|
||||
|
||||
@@ -76,14 +98,20 @@ SHyprlandVersion CPluginManager::getHyprlandVersion() {
|
||||
} catch (...) { ; }
|
||||
|
||||
if (m_bVerbose)
|
||||
std::cout << Colors::BLUE << "[v] " << Colors::RESET << "parsed commit " << hlcommit << " at branch " << hlbranch << " on " << hldate << ", commits " << commits << "\n";
|
||||
std::println("{}", verboseString("parsed commit {} at branch {} on {}, commits {}", hlcommit, hlbranch, hldate, commits));
|
||||
|
||||
auto ver = SHyprlandVersion{hlbranch, hlcommit, hldate, commits};
|
||||
|
||||
if (running)
|
||||
verRunning = ver;
|
||||
else
|
||||
verInstalled = ver;
|
||||
|
||||
ver = SHyprlandVersion{hlbranch, hlcommit, hldate, commits};
|
||||
return ver;
|
||||
}
|
||||
|
||||
bool CPluginManager::createSafeDirectory(const std::string& path) {
|
||||
if (path.empty() || !path.starts_with("/tmp"))
|
||||
if (path.empty() || !path.starts_with(getTempRoot()))
|
||||
return false;
|
||||
|
||||
if (std::filesystem::exists(path))
|
||||
@@ -102,20 +130,21 @@ bool CPluginManager::addNewPluginRepo(const std::string& url, const std::string&
|
||||
const auto HLVER = getHyprlandVersion();
|
||||
|
||||
if (!hasDeps()) {
|
||||
std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " Could not clone the plugin repository. Dependencies not satisfied. Hyprpm requires: cmake, meson, cpio\n";
|
||||
std::println(stderr, "\n{}", failureString("Could not clone the plugin repository. Dependencies not satisfied. Hyprpm requires: cmake, meson, cpio, pkg-config"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (DataState::pluginRepoExists(url)) {
|
||||
std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " Could not clone the plugin repository. Repository already installed.\n";
|
||||
std::println(stderr, "\n{}", failureString("Could not clone the plugin repository. Repository already installed."));
|
||||
return false;
|
||||
}
|
||||
|
||||
auto GLOBALSTATE = DataState::getGlobalState();
|
||||
if (!GLOBALSTATE.dontWarnInstall) {
|
||||
std::cout << Colors::YELLOW << "!" << Colors::RED << " Disclaimer:\n " << Colors::RESET
|
||||
<< "plugins, especially not official, have no guarantee of stability, availablity or security.\n Run them at your own risk.\n "
|
||||
<< "This message will not appear again.\n";
|
||||
std::println("{}!{} Disclaimer: {}", Colors::YELLOW, Colors::RED, Colors::RESET);
|
||||
std::println("plugins, especially not official, have no guarantee of stability, availablity or security.\n"
|
||||
"Run them at your own risk.\n"
|
||||
"This message will not appear again.");
|
||||
GLOBALSTATE.dontWarnInstall = true;
|
||||
DataState::updateGlobalState(GLOBALSTATE);
|
||||
}
|
||||
@@ -129,7 +158,7 @@ bool CPluginManager::addNewPluginRepo(const std::string& url, const std::string&
|
||||
std::getline(std::cin, input);
|
||||
|
||||
if (input.size() > 0 && input[0] != 'Y' && input[0] != 'y') {
|
||||
std::cout << "Aborting.\n";
|
||||
std::println(stderr, "Aborting.");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -140,73 +169,73 @@ bool CPluginManager::addNewPluginRepo(const std::string& url, const std::string&
|
||||
|
||||
progress.print();
|
||||
|
||||
if (!std::filesystem::exists("/tmp/hyprpm")) {
|
||||
std::filesystem::create_directory("/tmp/hyprpm");
|
||||
std::filesystem::permissions("/tmp/hyprpm", std::filesystem::perms::all, std::filesystem::perm_options::replace);
|
||||
} else if (!std::filesystem::is_directory("/tmp/hyprpm")) {
|
||||
std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " Could not prepare working dir for hyprpm\n";
|
||||
if (!std::filesystem::exists(getTempRoot())) {
|
||||
std::filesystem::create_directory(getTempRoot());
|
||||
std::filesystem::permissions(getTempRoot(), std::filesystem::perms::owner_all, std::filesystem::perm_options::replace);
|
||||
} else if (!std::filesystem::is_directory(getTempRoot())) {
|
||||
std::println(stderr, "\n{}", failureString("Could not prepare working dir for hyprpm"));
|
||||
return false;
|
||||
}
|
||||
|
||||
const std::string USERNAME = getpwuid(getuid())->pw_name;
|
||||
|
||||
m_szWorkingPluginDirectory = "/tmp/hyprpm/" + USERNAME;
|
||||
m_szWorkingPluginDirectory = getTempRoot() + USERNAME;
|
||||
|
||||
if (!createSafeDirectory(m_szWorkingPluginDirectory)) {
|
||||
std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " Could not prepare working dir for repo\n";
|
||||
std::println(stderr, "\n{}", failureString("Could not prepare working dir for repo"));
|
||||
return false;
|
||||
}
|
||||
|
||||
progress.printMessageAbove(std::string{Colors::RESET} + " → Cloning " + url);
|
||||
progress.printMessageAbove(infoString("Cloning {}", url));
|
||||
|
||||
std::string ret = execAndGet("cd /tmp/hyprpm && git clone --recursive " + url + " " + USERNAME);
|
||||
std::string ret = execAndGet(std::format("cd {} && git clone --recursive {} {}", getTempRoot(), url, USERNAME));
|
||||
|
||||
if (!std::filesystem::exists(m_szWorkingPluginDirectory + "/.git")) {
|
||||
std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " Could not clone the plugin repository. shell returned:\n" << ret << "\n";
|
||||
std::println(stderr, "\n{}", failureString("Could not clone the plugin repository. shell returned:\n{}", ret));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!rev.empty()) {
|
||||
std::string ret = execAndGet("git -C " + m_szWorkingPluginDirectory + " reset --hard --recurse-submodules " + rev);
|
||||
if (ret.compare(0, 6, "fatal:") == 0) {
|
||||
std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " Could not check out revision " << rev << ". shell returned:\n" << ret << "\n";
|
||||
std::println(stderr, "\n{}", failureString("Could not check out revision {}. shell returned:\n{}", rev, ret));
|
||||
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";
|
||||
std::println("{}", verboseString("git submodule update --init returned: {}", ret));
|
||||
}
|
||||
|
||||
progress.m_iSteps = 1;
|
||||
progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " cloned");
|
||||
progress.printMessageAbove(successString("cloned"));
|
||||
progress.m_szCurrentMessage = "Reading the manifest";
|
||||
progress.print();
|
||||
|
||||
std::unique_ptr<CManifest> pManifest;
|
||||
|
||||
if (std::filesystem::exists(m_szWorkingPluginDirectory + "/hyprpm.toml")) {
|
||||
progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " found hyprpm manifest");
|
||||
progress.printMessageAbove(successString("found hyprpm manifest"));
|
||||
pManifest = std::make_unique<CManifest>(MANIFEST_HYPRPM, m_szWorkingPluginDirectory + "/hyprpm.toml");
|
||||
} else if (std::filesystem::exists(m_szWorkingPluginDirectory + "/hyprload.toml")) {
|
||||
progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " found hyprload manifest");
|
||||
progress.printMessageAbove(successString("found hyprload manifest"));
|
||||
pManifest = std::make_unique<CManifest>(MANIFEST_HYPRLOAD, m_szWorkingPluginDirectory + "/hyprload.toml");
|
||||
}
|
||||
|
||||
if (!pManifest) {
|
||||
std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " The provided plugin repository does not have a valid manifest\n";
|
||||
std::println(stderr, "\n{}", failureString("The provided plugin repository does not have a valid manifest"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!pManifest->m_bGood) {
|
||||
std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " The provided plugin repository has a corrupted manifest\n";
|
||||
std::println(stderr, "\n{}", failureString("The provided plugin repository has a corrupted manifest"));
|
||||
return false;
|
||||
}
|
||||
|
||||
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) {
|
||||
std::string message = std::string{Colors::RESET} + " → " + pl.name + " by ";
|
||||
for (auto& a : pl.authors) {
|
||||
progress.printMessageAbove(successString("parsed manifest, found " + std::to_string(pManifest->m_vPlugins.size()) + " plugins:"));
|
||||
for (auto const& pl : pManifest->m_vPlugins) {
|
||||
std::string message = "→ " + pl.name + " by ";
|
||||
for (auto const& a : pl.authors) {
|
||||
message += a + ", ";
|
||||
}
|
||||
if (pl.authors.size() > 0) {
|
||||
@@ -220,19 +249,19 @@ bool CPluginManager::addNewPluginRepo(const std::string& url, const std::string&
|
||||
if (!pManifest->m_sRepository.commitPins.empty()) {
|
||||
// check commit pins
|
||||
|
||||
progress.printMessageAbove(std::string{Colors::RESET} + " → Manifest has " + std::to_string(pManifest->m_sRepository.commitPins.size()) + " pins, checking");
|
||||
progress.printMessageAbove(infoString("Manifest has {} pins, checking", pManifest->m_sRepository.commitPins.size()));
|
||||
|
||||
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");
|
||||
progress.printMessageAbove(successString("commit pin {} matched hl, resetting", plugin));
|
||||
|
||||
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";
|
||||
std::println("{}", verboseString("git submodule update --init returned: {}", ret));
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -244,12 +273,12 @@ bool CPluginManager::addNewPluginRepo(const std::string& url, const std::string&
|
||||
const auto HEADERSSTATUS = headersValid();
|
||||
|
||||
if (HEADERSSTATUS != HEADERS_OK) {
|
||||
std::cerr << "\n" << headerError(HEADERSSTATUS);
|
||||
std::println("\n{}", headerError(HEADERSSTATUS));
|
||||
return false;
|
||||
}
|
||||
|
||||
progress.m_iSteps = 3;
|
||||
progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " Hyprland headers OK");
|
||||
progress.printMessageAbove(successString("Hyprland headers OK"));
|
||||
progress.m_szCurrentMessage = "Building plugin(s)";
|
||||
progress.print();
|
||||
|
||||
@@ -257,35 +286,36 @@ bool CPluginManager::addNewPluginRepo(const std::string& url, const std::string&
|
||||
std::string out;
|
||||
|
||||
if (p.since > HLVER.commits && HLVER.commits >= 1 /* for --depth 1 clones, we can't check this. */) {
|
||||
progress.printMessageAbove(std::string{Colors::RED} + "✖" + Colors::RESET + " Not building " + p.name + ": your Hyprland version is too old.\n");
|
||||
progress.printMessageAbove(failureString("Not building {}: your Hyprland version is too old.\n", p.name));
|
||||
p.failed = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
progress.printMessageAbove(std::string{Colors::RESET} + " → Building " + p.name);
|
||||
progress.printMessageAbove(infoString("Building {}", p.name));
|
||||
|
||||
for (auto& bs : p.buildSteps) {
|
||||
std::string cmd = std::format("cd {} && PKG_CONFIG_PATH=\"{}/share/pkgconfig\" {}", m_szWorkingPluginDirectory, DataState::getHeadersPath(), bs);
|
||||
for (auto const& bs : p.buildSteps) {
|
||||
const std::string& cmd = std::format("cd {} && PKG_CONFIG_PATH=\"{}/share/pkgconfig\" {}", m_szWorkingPluginDirectory, DataState::getHeadersPath(), bs);
|
||||
out += " -> " + cmd + "\n" + execAndGet(cmd) + "\n";
|
||||
}
|
||||
|
||||
if (m_bVerbose)
|
||||
std::cout << Colors::BLUE << "[v] " << Colors::RESET << "shell returned: " << out << "\n";
|
||||
std::println("{}", verboseString("shell returned: {}", out));
|
||||
|
||||
if (!std::filesystem::exists(m_szWorkingPluginDirectory + "/" + p.output)) {
|
||||
progress.printMessageAbove(std::string{Colors::RED} + "✖" + Colors::RESET + " Plugin " + p.name + " failed to build.\n" +
|
||||
" This likely means that the plugin is either outdated, not yet available for your version, or broken.\n If you are on -git, update "
|
||||
"first.\n Try re-running with -v to see "
|
||||
"more verbose output.\n");
|
||||
progress.printMessageAbove(failureString("Plugin {} failed to build.\n"
|
||||
" This likely means that the plugin is either outdated, not yet available for your version, or broken.\n"
|
||||
" If you are on -git, update first\n"
|
||||
" Try re-running with -v to see more verbose output.\n",
|
||||
p.name));
|
||||
|
||||
p.failed = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " built " + p.name + " into " + p.output);
|
||||
progress.printMessageAbove(successString("built {} into {}", p.name, p.output));
|
||||
}
|
||||
|
||||
progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " all plugins built");
|
||||
progress.printMessageAbove(successString("all plugins built"));
|
||||
progress.m_iSteps = 4;
|
||||
progress.m_szCurrentMessage = "Installing repository";
|
||||
progress.print();
|
||||
@@ -299,18 +329,18 @@ 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);
|
||||
|
||||
progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " installed repository");
|
||||
progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " you can now enable the plugin(s) with hyprpm enable");
|
||||
progress.printMessageAbove(successString("installed repository"));
|
||||
progress.printMessageAbove(successString("you can now enable the plugin(s) with hyprpm enable"));
|
||||
progress.m_iSteps = 5;
|
||||
progress.m_szCurrentMessage = "Done!";
|
||||
progress.print();
|
||||
|
||||
std::cout << "\n";
|
||||
std::print("\n");
|
||||
|
||||
// remove build files
|
||||
std::filesystem::remove_all(m_szWorkingPluginDirectory);
|
||||
@@ -320,7 +350,7 @@ bool CPluginManager::addNewPluginRepo(const std::string& url, const std::string&
|
||||
|
||||
bool CPluginManager::removePluginRepo(const std::string& urlOrName) {
|
||||
if (!DataState::pluginRepoExists(urlOrName)) {
|
||||
std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " Could not remove the repository. Repository is not installed.\n";
|
||||
std::println(stderr, "\n{}", failureString("Could not remove the repository. Repository is not installed."));
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -331,7 +361,7 @@ bool CPluginManager::removePluginRepo(const std::string& urlOrName) {
|
||||
std::getline(std::cin, input);
|
||||
|
||||
if (input.size() > 0 && input[0] != 'Y' && input[0] != 'y') {
|
||||
std::cout << "Aborting.\n";
|
||||
std::println("Aborting.");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -341,13 +371,13 @@ bool CPluginManager::removePluginRepo(const std::string& urlOrName) {
|
||||
}
|
||||
|
||||
eHeadersErrors CPluginManager::headersValid() {
|
||||
const auto HLVER = getHyprlandVersion();
|
||||
const auto HLVER = getHyprlandVersion(false);
|
||||
|
||||
if (!std::filesystem::exists(DataState::getHeadersPath() + "/share/pkgconfig/hyprland.pc"))
|
||||
return HEADERS_MISSING;
|
||||
|
||||
// find headers commit
|
||||
std::string cmd = std::format("PKG_CONFIG_PATH=\"{}/share/pkgconfig\" pkgconf --cflags --keep-system-cflags hyprland", DataState::getHeadersPath());
|
||||
const std::string& cmd = std::format("PKG_CONFIG_PATH=\"{}/share/pkgconfig\" pkgconf --cflags --keep-system-cflags hyprland", DataState::getHeadersPath());
|
||||
auto headers = execAndGet(cmd.c_str());
|
||||
|
||||
if (!headers.contains("-I/"))
|
||||
@@ -355,7 +385,7 @@ eHeadersErrors CPluginManager::headersValid() {
|
||||
|
||||
headers.pop_back(); // pop newline
|
||||
|
||||
std::string verHeader = "";
|
||||
std::string verHeader;
|
||||
|
||||
while (!headers.empty()) {
|
||||
const auto PATH = headers.substr(0, headers.find(" -I/", 3));
|
||||
@@ -403,20 +433,20 @@ bool CPluginManager::updateHeaders(bool force) {
|
||||
|
||||
DataState::ensureStateStoreExists();
|
||||
|
||||
const auto HLVER = getHyprlandVersion();
|
||||
const auto HLVER = getHyprlandVersion(false);
|
||||
|
||||
if (!hasDeps()) {
|
||||
std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " Could not update. Dependencies not satisfied. Hyprpm requires: cmake, meson, cpio\n";
|
||||
std::println("\n{}", failureString("Could not update. Dependencies not satisfied. Hyprpm requires: cmake, meson, cpio, pkg-config"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!std::filesystem::exists("/tmp/hyprpm")) {
|
||||
std::filesystem::create_directory("/tmp/hyprpm");
|
||||
std::filesystem::permissions("/tmp/hyprpm", std::filesystem::perms::all, std::filesystem::perm_options::replace);
|
||||
if (!std::filesystem::exists(getTempRoot())) {
|
||||
std::filesystem::create_directory(getTempRoot());
|
||||
std::filesystem::permissions(getTempRoot(), std::filesystem::perms::owner_all, std::filesystem::perm_options::replace);
|
||||
}
|
||||
|
||||
if (!force && headersValid() == HEADERS_OK) {
|
||||
std::cout << "\n" << std::string{Colors::GREEN} + "✔" + Colors::RESET + " Headers up to date.\n";
|
||||
std::println("\n{}", successString("Headers up to date."));
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -427,77 +457,76 @@ bool CPluginManager::updateHeaders(bool force) {
|
||||
progress.print();
|
||||
|
||||
const std::string USERNAME = getpwuid(getuid())->pw_name;
|
||||
const auto WORKINGDIR = "/tmp/hyprpm/hyprland-" + USERNAME;
|
||||
const auto WORKINGDIR = getTempRoot() + "hyprland-" + USERNAME;
|
||||
|
||||
if (!createSafeDirectory(WORKINGDIR)) {
|
||||
std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " Could not prepare working dir for hl\n";
|
||||
std::println("\n{}", failureString("Could not prepare working dir for hl"));
|
||||
return false;
|
||||
}
|
||||
|
||||
progress.printMessageAbove(std::string{Colors::YELLOW} + "!" + Colors::RESET + " Cloning https://github.com/hyprwm/hyprland, this might take a moment.");
|
||||
progress.printMessageAbove(statusString("!", Colors::YELLOW, "Cloning https://github.com/hyprwm/Hyprland, this might take a moment."));
|
||||
|
||||
const bool bShallow = (HLVER.branch == "main" || HLVER.branch == "") && !m_bNoShallow;
|
||||
const bool bShallow = (HLVER.branch == "main") && !m_bNoShallow;
|
||||
|
||||
// let us give a bit of leg-room for shallowing
|
||||
// due to timezones, etc.
|
||||
const std::string SHALLOW_DATE =
|
||||
trim(HLVER.date).empty() ? "" : execAndGet("LC_TIME=\"en_US.UTF-8\" date --date='" + HLVER.date + " - 1 weeks' '+\%a \%b \%d \%H:\%M:\%S \%Y'");
|
||||
const std::string SHALLOW_DATE = 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);
|
||||
progress.printMessageAbove(verboseString("will shallow since: {}", SHALLOW_DATE));
|
||||
|
||||
std::string ret =
|
||||
execAndGet("cd /tmp/hyprpm && git clone --recursive https://github.com/hyprwm/hyprland hyprland-" + USERNAME + (bShallow ? " --shallow-since='" + SHALLOW_DATE + "'" : ""));
|
||||
std::string ret = execAndGet(std::format("cd {} && git clone --recursive https://github.com/hyprwm/Hyprland hyprland-{}{}", getTempRoot(), USERNAME,
|
||||
(bShallow ? " --shallow-since='" + SHALLOW_DATE + "'" : "")));
|
||||
|
||||
if (!std::filesystem::exists(WORKINGDIR)) {
|
||||
progress.printMessageAbove(std::string{Colors::RED} + "✖" + Colors::RESET + " Clone failed. Retrying without shallow.");
|
||||
ret = execAndGet("cd /tmp/hyprpm && git clone --recursive https://github.com/hyprwm/hyprland hyprland-" + USERNAME);
|
||||
progress.printMessageAbove(failureString("Clone failed. Retrying without shallow."));
|
||||
ret = execAndGet(std::format("cd {} && git clone --recursive https://github.com/hyprwm/hyprland hyprland-{}", getTempRoot(), USERNAME));
|
||||
}
|
||||
|
||||
if (!std::filesystem::exists(WORKINGDIR + "/.git")) {
|
||||
std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " Could not clone the hyprland repository. shell returned:\n" << ret << "\n";
|
||||
std::println(stderr, "\n{}", failureString("Could not clone the Hyprland repository. shell returned:\n{}", ret));
|
||||
return false;
|
||||
}
|
||||
|
||||
progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " cloned");
|
||||
progress.printMessageAbove(successString("Hyprland cloned"));
|
||||
progress.m_iSteps = 2;
|
||||
progress.m_szCurrentMessage = "Checking out sources";
|
||||
progress.print();
|
||||
|
||||
if (m_bVerbose)
|
||||
progress.printMessageAbove(std::string{Colors::BLUE} + "[v] " + Colors::RESET + "will run: " + "cd " + WORKINGDIR + " && git checkout " + HLVER.hash + " 2>&1");
|
||||
progress.printMessageAbove(verboseString("will run: cd {} && git checkout {} 2>&1", WORKINGDIR, HLVER.hash));
|
||||
|
||||
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";
|
||||
std::println(stderr, "\n{}",
|
||||
failureString("Could not checkout the running Hyprland commit. If you are on -git, try updating.\n"
|
||||
"You can also try re-running hyprpm update with --no-shallow."));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_bVerbose)
|
||||
progress.printMessageAbove(std::string{Colors::BLUE} + "[v] " + Colors::RESET + "git returned (co): " + ret);
|
||||
progress.printMessageAbove(verboseString("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);
|
||||
|
||||
if (m_bVerbose)
|
||||
progress.printMessageAbove(std::string{Colors::BLUE} + "[v] " + Colors::RESET + "git returned (rs): " + ret);
|
||||
progress.printMessageAbove(verboseString("git returned (rs): {}", ret));
|
||||
|
||||
progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " checked out to running ver");
|
||||
progress.printMessageAbove(successString("checked out to running ver"));
|
||||
progress.m_iSteps = 3;
|
||||
progress.m_szCurrentMessage = "Building Hyprland";
|
||||
progress.print();
|
||||
|
||||
progress.printMessageAbove(std::string{Colors::YELLOW} + "!" + Colors::RESET + " configuring Hyprland");
|
||||
progress.printMessageAbove(statusString("!", Colors::YELLOW, "configuring Hyprland"));
|
||||
|
||||
if (m_bVerbose)
|
||||
progress.printMessageAbove(std::string{Colors::BLUE} + "[v] " + Colors::RESET + "setting PREFIX for cmake to " + DataState::getHeadersPath());
|
||||
progress.printMessageAbove(verboseString("setting PREFIX for cmake to {}", DataState::getHeadersPath()));
|
||||
|
||||
ret = execAndGet(std::format("cd {} && cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:STRING=\"{}\" -S . -B ./build -G Ninja", WORKINGDIR,
|
||||
DataState::getHeadersPath()));
|
||||
if (m_bVerbose)
|
||||
progress.printMessageAbove(std::string{Colors::BLUE} + "[v] " + Colors::RESET + "cmake returned: " + ret);
|
||||
progress.printMessageAbove(verboseString("cmake returned: {}", ret));
|
||||
|
||||
if (ret.contains("CMake Error at")) {
|
||||
// missing deps, let the user know.
|
||||
@@ -506,48 +535,46 @@ bool CPluginManager::updateHeaders(bool force) {
|
||||
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\nThis likely means that you are missing the above dependencies or they are out of date.\n";
|
||||
std::println(stderr, "\n{}",
|
||||
failureString("Could not configure the hyprland source, cmake complained:\n{}\n\n"
|
||||
"This likely means that you are missing the above dependencies or they are out of date.",
|
||||
missing));
|
||||
return false;
|
||||
}
|
||||
|
||||
progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " configured Hyprland");
|
||||
progress.printMessageAbove(successString("configured Hyprland"));
|
||||
progress.m_iSteps = 4;
|
||||
progress.m_szCurrentMessage = "Installing sources";
|
||||
progress.print();
|
||||
|
||||
std::string cmd =
|
||||
const std::string& cmd =
|
||||
std::format("sed -i -e \"s#PREFIX = /usr/local#PREFIX = {}#\" {}/Makefile && cd {} && make installheaders", DataState::getHeadersPath(), WORKINGDIR, WORKINGDIR);
|
||||
if (m_bVerbose)
|
||||
progress.printMessageAbove(std::string{Colors::BLUE} + "[v] " + Colors::RESET + "installation will run: " + cmd);
|
||||
progress.printMessageAbove(verboseString("installation will run: {}", cmd));
|
||||
|
||||
ret = execAndGet(cmd);
|
||||
|
||||
if (m_bVerbose)
|
||||
std::cout << Colors::BLUE << "[v] " << Colors::RESET << "installer returned: " << ret << "\n";
|
||||
std::println("{}", verboseString("installer returned: {}", ret));
|
||||
|
||||
// remove build files
|
||||
std::filesystem::remove_all(WORKINGDIR);
|
||||
|
||||
auto HEADERSVALID = headersValid();
|
||||
if (HEADERSVALID == HEADERS_OK) {
|
||||
progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " installed headers");
|
||||
progress.printMessageAbove(successString("installed headers"));
|
||||
progress.m_iSteps = 5;
|
||||
progress.m_szCurrentMessage = "Done!";
|
||||
progress.print();
|
||||
|
||||
std::cout << "\n";
|
||||
std::print("\n");
|
||||
} else {
|
||||
progress.printMessageAbove(std::string{Colors::RED} + "✖" + Colors::RESET + " failed to install headers with error code " + std::to_string((int)HEADERSVALID) + " (" +
|
||||
headerErrorShort(HEADERSVALID) + ")");
|
||||
progress.printMessageAbove(failureString("failed to install headers with error code {} ({})", (int)HEADERSVALID, headerErrorShort(HEADERSVALID)));
|
||||
progress.m_iSteps = 5;
|
||||
progress.m_szCurrentMessage = "Failed";
|
||||
progress.print();
|
||||
|
||||
std::cout << "\n";
|
||||
|
||||
std::cerr << "\n" << headerError(HEADERSVALID);
|
||||
std::print(stderr, "\n\n{}", headerError(HEADERSVALID));
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -557,18 +584,18 @@ bool CPluginManager::updateHeaders(bool force) {
|
||||
|
||||
bool CPluginManager::updatePlugins(bool forceUpdateAll) {
|
||||
if (headersValid() != HEADERS_OK) {
|
||||
std::cout << "\n" << std::string{Colors::RED} + "✖" + Colors::RESET + " headers are not up-to-date, please run hyprpm update.\n";
|
||||
std::println("{}", failureString("headers are not up-to-date, please run hyprpm update."));
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto REPOS = DataState::getAllRepositories();
|
||||
|
||||
if (REPOS.size() < 1) {
|
||||
std::cout << "\n" << std::string{Colors::RED} + "✖" + Colors::RESET + " No repos to update.\n";
|
||||
std::println("{}", failureString("No repos to update."));
|
||||
return true;
|
||||
}
|
||||
|
||||
const auto HLVER = getHyprlandVersion();
|
||||
const auto HLVER = getHyprlandVersion(false);
|
||||
|
||||
CProgressBar progress;
|
||||
progress.m_iMaxSteps = REPOS.size() * 2 + 2;
|
||||
@@ -577,34 +604,35 @@ bool CPluginManager::updatePlugins(bool forceUpdateAll) {
|
||||
progress.print();
|
||||
|
||||
const std::string USERNAME = getpwuid(getuid())->pw_name;
|
||||
m_szWorkingPluginDirectory = "/tmp/hyprpm/" + USERNAME;
|
||||
m_szWorkingPluginDirectory = getTempRoot() + USERNAME;
|
||||
|
||||
for (auto& repo : REPOS) {
|
||||
for (auto const& repo : REPOS) {
|
||||
bool update = forceUpdateAll;
|
||||
|
||||
progress.m_iSteps++;
|
||||
progress.m_szCurrentMessage = "Updating " + repo.name;
|
||||
progress.print();
|
||||
|
||||
progress.printMessageAbove(std::string{Colors::RESET} + " → checking for updates for " + repo.name);
|
||||
progress.printMessageAbove(infoString("checking for updates for {}", repo.name));
|
||||
|
||||
createSafeDirectory(m_szWorkingPluginDirectory);
|
||||
|
||||
progress.printMessageAbove(std::string{Colors::RESET} + " → Cloning " + repo.url);
|
||||
progress.printMessageAbove(infoString("Cloning {}", repo.url));
|
||||
|
||||
std::string ret = execAndGet("cd /tmp/hyprpm && git clone --recursive " + repo.url + " " + USERNAME);
|
||||
std::string ret = execAndGet(std::format("cd {} && git clone --recursive {} {}", getTempRoot(), repo.url, USERNAME));
|
||||
|
||||
if (!std::filesystem::exists(m_szWorkingPluginDirectory + "/.git")) {
|
||||
std::cout << "\n" << std::string{Colors::RED} + "✖" + Colors::RESET + " could not clone repo: shell returned:\n" + ret;
|
||||
std::println("{}", failureString("could not clone repo: shell returned: {}", ret));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!repo.rev.empty()) {
|
||||
progress.printMessageAbove(std::string{Colors::RESET} + " → Plugin has revision set, resetting: " + repo.rev);
|
||||
progress.printMessageAbove(infoString("Plugin has revision set, resetting: {}", repo.rev));
|
||||
|
||||
std::string ret = execAndGet("git -C " + m_szWorkingPluginDirectory + " reset --hard --recurse-submodules " + repo.rev);
|
||||
if (ret.compare(0, 6, "fatal:") == 0) {
|
||||
std::cout << "\n" << std::string{Colors::RED} + "✖" + Colors::RESET + " could not check out revision " + repo.rev + ": shell returned:\n" + ret;
|
||||
std::println(stderr, "\n{}", failureString("could not check out revision {}: shell returned:\n{}", repo.rev, ret));
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -620,7 +648,7 @@ bool CPluginManager::updatePlugins(bool forceUpdateAll) {
|
||||
|
||||
if (!update) {
|
||||
std::filesystem::remove_all(m_szWorkingPluginDirectory);
|
||||
progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " repository " + repo.name + " is up-to-date.");
|
||||
progress.printMessageAbove(successString("repository {} is up-to-date.", repo.name));
|
||||
progress.m_iSteps++;
|
||||
progress.print();
|
||||
continue;
|
||||
@@ -628,41 +656,41 @@ bool CPluginManager::updatePlugins(bool forceUpdateAll) {
|
||||
|
||||
// we need to update
|
||||
|
||||
progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " repository " + repo.name + " has updates.");
|
||||
progress.printMessageAbove(std::string{Colors::RESET} + " → Building " + repo.name);
|
||||
progress.printMessageAbove(successString("repository {} has updates.", repo.name));
|
||||
progress.printMessageAbove(infoString("Building {}", repo.name));
|
||||
progress.m_iSteps++;
|
||||
progress.print();
|
||||
|
||||
std::unique_ptr<CManifest> pManifest;
|
||||
|
||||
if (std::filesystem::exists(m_szWorkingPluginDirectory + "/hyprpm.toml")) {
|
||||
progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " found hyprpm manifest");
|
||||
progress.printMessageAbove(successString("found hyprpm manifest"));
|
||||
pManifest = std::make_unique<CManifest>(MANIFEST_HYPRPM, m_szWorkingPluginDirectory + "/hyprpm.toml");
|
||||
} else if (std::filesystem::exists(m_szWorkingPluginDirectory + "/hyprload.toml")) {
|
||||
progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " found hyprload manifest");
|
||||
progress.printMessageAbove(successString("found hyprload manifest"));
|
||||
pManifest = std::make_unique<CManifest>(MANIFEST_HYPRLOAD, m_szWorkingPluginDirectory + "/hyprload.toml");
|
||||
}
|
||||
|
||||
if (!pManifest) {
|
||||
std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " The provided plugin repository does not have a valid manifest\n";
|
||||
std::println(stderr, "\n{}", failureString("The provided plugin repository does not have a valid manifest"));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!pManifest->m_bGood) {
|
||||
std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " The provided plugin repository has a corrupted manifest\n";
|
||||
std::println(stderr, "\n{}", failureString("The provided plugin repository has a corrupted manifest"));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (repo.rev.empty() && !pManifest->m_sRepository.commitPins.empty()) {
|
||||
// check commit pins unless a revision is specified
|
||||
|
||||
progress.printMessageAbove(std::string{Colors::RESET} + " → Manifest has " + std::to_string(pManifest->m_sRepository.commitPins.size()) + " pins, checking");
|
||||
progress.printMessageAbove(infoString("Manifest has {} pins, checking", pManifest->m_sRepository.commitPins.size()));
|
||||
|
||||
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");
|
||||
progress.printMessageAbove(successString("commit pin {} matched hl, resetting", plugin));
|
||||
|
||||
execAndGet("cd " + m_szWorkingPluginDirectory + " && git reset --hard --recurse-submodules " + plugin);
|
||||
}
|
||||
@@ -672,32 +700,33 @@ bool CPluginManager::updatePlugins(bool forceUpdateAll) {
|
||||
std::string out;
|
||||
|
||||
if (p.since > HLVER.commits && HLVER.commits >= 1000 /* for shallow clones, we can't check this. 1000 is an arbitrary number I chose. */) {
|
||||
progress.printMessageAbove(std::string{Colors::RED} + "✖" + Colors::RESET + " Not building " + p.name + ": your Hyprland version is too old.\n");
|
||||
progress.printMessageAbove(failureString("Not building {}: your Hyprland version is too old.\n", p.name));
|
||||
p.failed = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
progress.printMessageAbove(std::string{Colors::RESET} + " → Building " + p.name);
|
||||
progress.printMessageAbove(infoString("Building {}", p.name));
|
||||
|
||||
for (auto& bs : p.buildSteps) {
|
||||
std::string cmd = std::format("cd {} && PKG_CONFIG_PATH=\"{}/share/pkgconfig\" {}", m_szWorkingPluginDirectory, DataState::getHeadersPath(), bs);
|
||||
for (auto const& bs : p.buildSteps) {
|
||||
const std::string& cmd = std::format("cd {} && PKG_CONFIG_PATH=\"{}/share/pkgconfig\" {}", m_szWorkingPluginDirectory, DataState::getHeadersPath(), bs);
|
||||
out += " -> " + cmd + "\n" + execAndGet(cmd) + "\n";
|
||||
}
|
||||
|
||||
if (m_bVerbose)
|
||||
std::cout << Colors::BLUE << "[v] " << Colors::RESET << "shell returned: " << out << "\n";
|
||||
std::println("{}", verboseString("shell returned: {}", out));
|
||||
|
||||
if (!std::filesystem::exists(m_szWorkingPluginDirectory + "/" + p.output)) {
|
||||
std::cerr << "\n"
|
||||
<< Colors::RED << "✖" << Colors::RESET << " Plugin " << p.name << " failed to build.\n"
|
||||
<< " This likely means that the plugin is either outdated, not yet available for your version, or broken.\n If you are on -git, update first.\n Try "
|
||||
"re-running with -v to see more verbose "
|
||||
"output.\n";
|
||||
std::println(stderr,
|
||||
"\n{}\n"
|
||||
" This likely means that the plugin is either outdated, not yet available for your version, or broken.\n"
|
||||
"If you are on -git, update first.\n"
|
||||
"Try re-running with -v to see more verbose output.",
|
||||
failureString("Plugin {} failed to build.", p.name));
|
||||
p.failed = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " built " + p.name + " into " + p.output);
|
||||
progress.printMessageAbove(successString("built {} into {}", p.name, p.output));
|
||||
}
|
||||
|
||||
// add repo toml to DataState
|
||||
@@ -709,7 +738,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});
|
||||
}
|
||||
@@ -718,7 +747,7 @@ bool CPluginManager::updatePlugins(bool forceUpdateAll) {
|
||||
|
||||
std::filesystem::remove_all(m_szWorkingPluginDirectory);
|
||||
|
||||
progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " updated " + repo.name);
|
||||
progress.printMessageAbove(successString("updated {}", repo.name));
|
||||
}
|
||||
|
||||
progress.m_iSteps++;
|
||||
@@ -733,7 +762,7 @@ bool CPluginManager::updatePlugins(bool forceUpdateAll) {
|
||||
progress.m_szCurrentMessage = "Done!";
|
||||
progress.print();
|
||||
|
||||
std::cout << "\n";
|
||||
std::print("\n");
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -741,27 +770,27 @@ bool CPluginManager::updatePlugins(bool forceUpdateAll) {
|
||||
bool CPluginManager::enablePlugin(const std::string& name) {
|
||||
bool ret = DataState::setPluginEnabled(name, true);
|
||||
if (ret)
|
||||
std::cout << Colors::GREEN << "✔" << Colors::RESET << " Enabled " << name << "\n";
|
||||
std::println("{}", successString("Enabled {}", name));
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool CPluginManager::disablePlugin(const std::string& name) {
|
||||
bool ret = DataState::setPluginEnabled(name, false);
|
||||
if (ret)
|
||||
std::cout << Colors::GREEN << "✔" << Colors::RESET << " Disabled " << name << "\n";
|
||||
std::println("{}", successString("Disabled {}", name));
|
||||
return ret;
|
||||
}
|
||||
|
||||
ePluginLoadStateReturn CPluginManager::ensurePluginsLoadState() {
|
||||
if (headersValid() != HEADERS_OK) {
|
||||
std::cerr << "\n" << std::string{Colors::RED} + "✖" + Colors::RESET + " headers are not up-to-date, please run hyprpm update.\n";
|
||||
std::println(stderr, "\n{}", failureString("headers are not up-to-date, please run hyprpm update."));
|
||||
return LOADSTATE_HEADERS_OUTDATED;
|
||||
}
|
||||
|
||||
const auto HOME = getenv("HOME");
|
||||
const auto HIS = getenv("HYPRLAND_INSTANCE_SIGNATURE");
|
||||
if (!HOME || !HIS) {
|
||||
std::cerr << "PluginManager: no $HOME or HIS\n";
|
||||
std::println(stderr, "PluginManager: no $HOME or HIS");
|
||||
return LOADSTATE_FAIL;
|
||||
}
|
||||
const auto HYPRPMPATH = DataState::getDataStatePath() + "/";
|
||||
@@ -770,14 +799,14 @@ ePluginLoadStateReturn CPluginManager::ensurePluginsLoadState() {
|
||||
|
||||
std::vector<std::string> loadedPlugins;
|
||||
|
||||
std::cout << Colors::GREEN << "✔" << Colors::RESET << " Ensuring plugin load state\n";
|
||||
std::println("{}", successString("Ensuring plugin load state"));
|
||||
|
||||
// iterate line by line
|
||||
while (!pluginLines.empty()) {
|
||||
auto plLine = pluginLines.substr(0, pluginLines.find("\n"));
|
||||
auto plLine = pluginLines.substr(0, pluginLines.find('\n'));
|
||||
|
||||
if (pluginLines.find("\n") != std::string::npos)
|
||||
pluginLines = pluginLines.substr(pluginLines.find("\n") + 1);
|
||||
if (pluginLines.find('\n') != std::string::npos)
|
||||
pluginLines = pluginLines.substr(pluginLines.find('\n') + 1);
|
||||
else
|
||||
pluginLines = "";
|
||||
|
||||
@@ -794,8 +823,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;
|
||||
}
|
||||
@@ -805,8 +834,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;
|
||||
}
|
||||
@@ -815,35 +844,54 @@ ePluginLoadStateReturn CPluginManager::ensurePluginsLoadState() {
|
||||
return "";
|
||||
};
|
||||
|
||||
// if any of the loadUnloadPlugin calls return false, this is true
|
||||
// bcs that means the header version doesn't match the running version
|
||||
// (and Hyprland needs to restart)
|
||||
bool hyprlandVersionMismatch = false;
|
||||
|
||||
// unload disabled plugins
|
||||
for (auto& p : loadedPlugins) {
|
||||
for (auto const& p : loadedPlugins) {
|
||||
if (!enabled(p)) {
|
||||
// unload
|
||||
loadUnloadPlugin(HYPRPMPATH + repoForName(p) + "/" + p + ".so", false);
|
||||
std::cout << Colors::GREEN << "✔" << Colors::RESET << " Unloaded " << p << "\n";
|
||||
if (!loadUnloadPlugin(HYPRPMPATH + repoForName(p) + "/" + p + ".so", false)) {
|
||||
std::println("{}", infoString("{} will be unloaded after restarting Hyprland", p));
|
||||
hyprlandVersionMismatch = true;
|
||||
} else
|
||||
std::println("{}", successString("Unloaded {}", p));
|
||||
}
|
||||
}
|
||||
|
||||
// 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;
|
||||
|
||||
if (std::find_if(loadedPlugins.begin(), loadedPlugins.end(), [&](const auto& other) { return other == p.name; }) != loadedPlugins.end())
|
||||
continue;
|
||||
|
||||
loadUnloadPlugin(HYPRPMPATH + repoForName(p.name) + "/" + p.filename, true);
|
||||
std::cout << Colors::GREEN << "✔" << Colors::RESET << " Loaded " << p.name << "\n";
|
||||
if (!loadUnloadPlugin(HYPRPMPATH + repoForName(p.name) + "/" + p.filename, true)) {
|
||||
std::println("{}", infoString("{} will be loaded after restarting Hyprland", p.name));
|
||||
hyprlandVersionMismatch = true;
|
||||
} else
|
||||
std::println("{}", successString("Loaded {}", p.name));
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << Colors::GREEN << "✔" << Colors::RESET << " Plugin load state ensured\n";
|
||||
std::println("{}", successString("Plugin load state ensured"));
|
||||
|
||||
return LOADSTATE_OK;
|
||||
return hyprlandVersionMismatch ? LOADSTATE_HYPRLAND_UPDATED : LOADSTATE_OK;
|
||||
}
|
||||
|
||||
bool CPluginManager::loadUnloadPlugin(const std::string& path, bool load) {
|
||||
auto state = DataState::getGlobalState();
|
||||
auto HLVER = getHyprlandVersion(true);
|
||||
|
||||
if (state.headersHashCompiled != HLVER.hash) {
|
||||
std::println("{}", infoString("Running Hyprland version differs from plugin state, please restart Hyprland."));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (load)
|
||||
execAndGet("hyprctl plugin load " + path);
|
||||
else
|
||||
@@ -855,17 +903,18 @@ bool CPluginManager::loadUnloadPlugin(const std::string& path, bool load) {
|
||||
void CPluginManager::listAllPlugins() {
|
||||
const auto REPOS = DataState::getAllRepositories();
|
||||
|
||||
for (auto& r : REPOS) {
|
||||
std::cout << std::string{Colors::RESET} + " → Repository " + r.name + ":\n";
|
||||
for (auto const& r : REPOS) {
|
||||
std::println("{}", infoString("Repository {}:", r.name));
|
||||
|
||||
for (auto& p : r.plugins) {
|
||||
|
||||
std::cout << std::string{Colors::RESET} + " │ Plugin " + p.name;
|
||||
for (auto const& p : r.plugins) {
|
||||
std::println(" │ Plugin {}", p.name);
|
||||
|
||||
if (!p.failed)
|
||||
std::cout << "\n └─ enabled: " << (p.enabled ? Colors::GREEN : Colors::RED) << (p.enabled ? "true" : "false") << Colors::RESET << "\n";
|
||||
std::println(" └─ enabled: {}", (p.enabled ? std::string{Colors::GREEN} + "true" : std::string{Colors::RED} + "false"));
|
||||
else
|
||||
std::cout << "\n └─ enabled: " << Colors::RED << "Plugin failed to build" << Colors::RESET << "\n";
|
||||
std::println(" └─ enabled: {}Plugin failed to build", Colors::RED);
|
||||
|
||||
std::println("{}", Colors::RESET);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -876,19 +925,19 @@ void CPluginManager::notify(const eNotifyIcons icon, uint32_t color, int duratio
|
||||
|
||||
std::string CPluginManager::headerError(const eHeadersErrors err) {
|
||||
switch (err) {
|
||||
case HEADERS_CORRUPTED: return std::string{Colors::RED} + "✖" + Colors::RESET + " Headers corrupted. Please run hyprpm update to fix those.\n";
|
||||
case HEADERS_MISMATCHED: return std::string{Colors::RED} + "✖" + Colors::RESET + " Headers version mismatch. Please run hyprpm update to fix those.\n";
|
||||
case HEADERS_NOT_HYPRLAND: return std::string{Colors::RED} + "✖" + Colors::RESET + " It doesn't seem you are running on hyprland.\n";
|
||||
case HEADERS_MISSING: return std::string{Colors::RED} + "✖" + Colors::RESET + " Headers missing. Please run hyprpm update to fix those.\n";
|
||||
case HEADERS_CORRUPTED: return failureString("Headers corrupted. Please run hyprpm update to fix those.\n");
|
||||
case HEADERS_MISMATCHED: return failureString("Headers version mismatch. Please run hyprpm update to fix those.\n");
|
||||
case HEADERS_NOT_HYPRLAND: return failureString("It doesn't seem you are running on hyprland.\n");
|
||||
case HEADERS_MISSING: return failureString("Headers missing. Please run hyprpm update to fix those.\n");
|
||||
case HEADERS_DUPLICATED: {
|
||||
return std::string{Colors::RED} + "✖" + Colors::RESET + " Headers duplicated!!! This is a very bad sign.\n" +
|
||||
" This could be due to e.g. installing hyprland manually while a system package of hyprland is also installed.\n" +
|
||||
" If the above doesn't apply, check your /usr/include and /usr/local/include directories\n and remove all the hyprland headers.\n";
|
||||
return failureString("Headers duplicated!!! This is a very bad sign.\n"
|
||||
"This could be due to e.g. installing hyprland manually while a system package of hyprland is also installed.\n"
|
||||
"If the above doesn't apply, check your /usr/include and /usr/local/include directories\n and remove all the hyprland headers.\n");
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
|
||||
return std::string{Colors::RED} + "✖" + Colors::RESET + " Unknown header error. Please run hyprpm update to fix those.\n";
|
||||
return failureString("Unknown header error. Please run hyprpm update to fix those.\n");
|
||||
}
|
||||
|
||||
std::string CPluginManager::headerErrorShort(const eHeadersErrors err) {
|
||||
@@ -904,9 +953,9 @@ std::string CPluginManager::headerErrorShort(const eHeadersErrors err) {
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
enum eHeadersErrors {
|
||||
HEADERS_OK = 0,
|
||||
@@ -26,7 +27,8 @@ enum ePluginLoadStateReturn {
|
||||
LOADSTATE_OK = 0,
|
||||
LOADSTATE_FAIL,
|
||||
LOADSTATE_PARTIAL_FAIL,
|
||||
LOADSTATE_HEADERS_OUTDATED
|
||||
LOADSTATE_HEADERS_OUTDATED,
|
||||
LOADSTATE_HYPRLAND_UPDATED
|
||||
};
|
||||
|
||||
struct SHyprlandVersion {
|
||||
@@ -52,7 +54,7 @@ class CPluginManager {
|
||||
ePluginLoadStateReturn ensurePluginsLoadState();
|
||||
|
||||
bool loadUnloadPlugin(const std::string& path, bool load);
|
||||
SHyprlandVersion getHyprlandVersion();
|
||||
SHyprlandVersion getHyprlandVersion(bool running = true);
|
||||
|
||||
void notify(const eNotifyIcons icon, uint32_t color, int durationMs, const std::string& message);
|
||||
|
||||
@@ -68,7 +70,7 @@ class CPluginManager {
|
||||
std::string headerError(const eHeadersErrors err);
|
||||
std::string headerErrorShort(const eHeadersErrors err);
|
||||
|
||||
std::string m_szWorkingPluginDirectory = "";
|
||||
std::string m_szWorkingPluginDirectory;
|
||||
};
|
||||
|
||||
inline std::unique_ptr<CPluginManager> g_pPluginManager;
|
||||
|
32
hyprpm/src/helpers/StringUtils.hpp
Normal file
@@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
#include <format>
|
||||
#include <string>
|
||||
#include "Colors.hpp"
|
||||
|
||||
template <typename... Args>
|
||||
std::string statusString(const std::string_view emoji, const std::string_view color, const std::string_view fmt, Args&&... args) {
|
||||
std::string ret = std::format("{}{}{} ", color, emoji, Colors::RESET);
|
||||
ret += std::vformat(fmt, std::make_format_args(args...));
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
std::string successString(const std::string_view fmt, Args&&... args) {
|
||||
return statusString("✔", Colors::GREEN, fmt, args...);
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
std::string failureString(const std::string_view fmt, Args&&... args) {
|
||||
return statusString("✖", Colors::RED, fmt, args...);
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
std::string verboseString(const std::string_view fmt, Args&&... args) {
|
||||
return statusString("[v]", Colors::BLUE, fmt, args...);
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
std::string infoString(const std::string_view fmt, Args&&... args) {
|
||||
return statusString("→", Colors::RESET, fmt, args...);
|
||||
}
|
@@ -1,15 +1,16 @@
|
||||
#include "progress/CProgressBar.hpp"
|
||||
#include "helpers/Colors.hpp"
|
||||
#include "helpers/StringUtils.hpp"
|
||||
#include "core/PluginManager.hpp"
|
||||
#include "core/DataState.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <cstdio>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <print>
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
|
||||
const std::string HELP = R"#(┏ hyprpm, a Hyprland Plugin Manager
|
||||
constexpr std::string_view HELP = R"#(┏ hyprpm, a Hyprland Plugin Manager
|
||||
┃
|
||||
┣ add [url] [git rev] → Install a new plugin repository from git. Git revision
|
||||
┃ is optional, when set, commit locks are ignored.
|
||||
@@ -22,7 +23,8 @@ const std::string HELP = R"#(┏ hyprpm, a Hyprland Plugin Manager
|
||||
┃
|
||||
┣ Flags:
|
||||
┃
|
||||
┣ --notify | -n → Send a hyprland notification for important events (e.g. load fail)
|
||||
┣ --notify | -n → Send a hyprland notification for important events (including both successes and fail events)
|
||||
┣ --notify-fail | -nn → Send a hyprland notification for fail events only
|
||||
┣ --help | -h → Show this menu
|
||||
┣ --verbose | -v → Enable too much logging
|
||||
┣ --force | -f → Force an operation ignoring checks (e.g. update -f)
|
||||
@@ -37,29 +39,31 @@ int main(int argc, char** argv, char** envp) {
|
||||
}
|
||||
|
||||
if (ARGS.size() < 2) {
|
||||
std::cout << HELP;
|
||||
std::println(stderr, "{}", HELP);
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::vector<std::string> command;
|
||||
bool notify = false, verbose = false, force = false, noShallow = false;
|
||||
bool notify = false, notifyFail = false, verbose = false, force = false, noShallow = false;
|
||||
|
||||
for (int i = 1; i < argc; ++i) {
|
||||
if (ARGS[i].starts_with("-")) {
|
||||
if (ARGS[i] == "--help" || ARGS[i] == "-h") {
|
||||
std::cout << HELP;
|
||||
std::println("{}", HELP);
|
||||
return 0;
|
||||
} else if (ARGS[i] == "--notify" || ARGS[i] == "-n") {
|
||||
notify = true;
|
||||
} else if (ARGS[i] == "--notify-fail" || ARGS[i] == "-nn") {
|
||||
notifyFail = 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";
|
||||
std::println("{}", statusString("!", Colors::RED, "Using --force, I hope you know what you are doing."));
|
||||
} else {
|
||||
std::cerr << "Unrecognized option " << ARGS[i] << "\n";
|
||||
std::println(stderr, "Unrecognized option {}", ARGS[i]);
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
@@ -68,7 +72,7 @@ int main(int argc, char** argv, char** envp) {
|
||||
}
|
||||
|
||||
if (command.empty()) {
|
||||
std::cout << HELP;
|
||||
std::println(stderr, "{}", HELP);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -78,7 +82,7 @@ int main(int argc, char** argv, char** envp) {
|
||||
|
||||
if (command[0] == "add") {
|
||||
if (command.size() < 2) {
|
||||
std::cerr << Colors::RED << "✖" << Colors::RESET << " Not enough args for add.\n";
|
||||
std::println(stderr, "{}", failureString("Not enough args for add."));
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -90,7 +94,7 @@ int main(int argc, char** argv, char** envp) {
|
||||
return g_pPluginManager->addNewPluginRepo(command[1], rev) ? 0 : 1;
|
||||
} else if (command[0] == "remove") {
|
||||
if (ARGS.size() < 2) {
|
||||
std::cerr << Colors::RED << "✖" << Colors::RESET << " Not enough args for remove.\n";
|
||||
std::println(stderr, "{}", failureString("Not enough args for remove."));
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -99,7 +103,7 @@ int main(int argc, char** argv, char** envp) {
|
||||
bool headersValid = g_pPluginManager->headersValid() == HEADERS_OK;
|
||||
bool headers = g_pPluginManager->updateHeaders(force);
|
||||
if (headers) {
|
||||
const auto HLVER = g_pPluginManager->getHyprlandVersion();
|
||||
const auto HLVER = g_pPluginManager->getHyprlandVersion(false);
|
||||
auto GLOBALSTATE = DataState::getGlobalState();
|
||||
const auto COMPILEDOUTDATED = HLVER.hash != GLOBALSTATE.headersHashCompiled;
|
||||
|
||||
@@ -110,32 +114,39 @@ int main(int argc, char** argv, char** envp) {
|
||||
|
||||
auto ret2 = g_pPluginManager->ensurePluginsLoadState();
|
||||
|
||||
if (ret2 == LOADSTATE_HYPRLAND_UPDATED)
|
||||
g_pPluginManager->notify(ICON_INFO, 0, 10000, "[hyprpm] Updated plugins, but Hyprland was updated. Please restart Hyprland.");
|
||||
|
||||
if (ret2 != LOADSTATE_OK)
|
||||
return 1;
|
||||
} else if (notify)
|
||||
g_pPluginManager->notify(ICON_ERROR, 0, 10000, "[hyprpm] Couldn't update headers");
|
||||
} else if (command[0] == "enable") {
|
||||
if (ARGS.size() < 2) {
|
||||
std::cerr << Colors::RED << "✖" << Colors::RESET << " Not enough args for enable.\n";
|
||||
std::println(stderr, "{}", failureString("Not enough args for enable."));
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!g_pPluginManager->enablePlugin(command[1])) {
|
||||
std::cerr << Colors::RED << "✖" << Colors::RESET << " Couldn't enable plugin (missing?)\n";
|
||||
std::println(stderr, "{}", failureString("Couldn't enable plugin (missing?)"));
|
||||
return 1;
|
||||
}
|
||||
|
||||
auto ret = g_pPluginManager->ensurePluginsLoadState();
|
||||
|
||||
if (ret == LOADSTATE_HYPRLAND_UPDATED)
|
||||
g_pPluginManager->notify(ICON_INFO, 0, 10000, "[hyprpm] Enabled plugin, but Hyprland was updated. Please restart Hyprland.");
|
||||
|
||||
if (ret != LOADSTATE_OK)
|
||||
return 1;
|
||||
} else if (command[0] == "disable") {
|
||||
if (command.size() < 2) {
|
||||
std::cerr << Colors::RED << "✖" << Colors::RESET << " Not enough args for disable.\n";
|
||||
std::println(stderr, "{}", failureString("Not enough args for disable."));
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!g_pPluginManager->disablePlugin(command[1])) {
|
||||
std::cerr << Colors::RED << "✖" << Colors::RESET << " Couldn't disable plugin (missing?)\n";
|
||||
std::println(stderr, "{}", failureString("Couldn't disable plugin (missing?)"));
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -154,13 +165,13 @@ int main(int argc, char** argv, char** envp) {
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
} else if (notify) {
|
||||
} else if (notify && !notifyFail) {
|
||||
g_pPluginManager->notify(ICON_OK, 0, 4000, "[hyprpm] Loaded plugins");
|
||||
}
|
||||
} else if (command[0] == "list") {
|
||||
g_pPluginManager->listAllPlugins();
|
||||
} else {
|
||||
std::cout << HELP;
|
||||
std::println(stderr, "{}", HELP);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@@ -1,15 +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',
|
||||
)
|
||||
|
@@ -1,11 +1,11 @@
|
||||
#include "CProgressBar.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <sys/ioctl.h>
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <format>
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <print>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
@@ -16,11 +16,12 @@ void CProgressBar::printMessageAbove(const std::string& msg) {
|
||||
ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
|
||||
|
||||
std::string spaces;
|
||||
spaces.reserve(w.ws_col);
|
||||
for (size_t i = 0; i < w.ws_col; ++i) {
|
||||
spaces += ' ';
|
||||
}
|
||||
|
||||
std::cout << "\r" << spaces << "\r" << msg << "\n";
|
||||
std::println("\r{}\r{}", spaces, msg);
|
||||
print();
|
||||
}
|
||||
|
||||
@@ -29,15 +30,16 @@ void CProgressBar::print() {
|
||||
ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
|
||||
|
||||
if (m_bFirstPrint)
|
||||
std::cout << "\n";
|
||||
std::print("\n");
|
||||
m_bFirstPrint = false;
|
||||
|
||||
std::string spaces;
|
||||
spaces.reserve(w.ws_col);
|
||||
for (size_t i = 0; i < w.ws_col; ++i) {
|
||||
spaces += ' ';
|
||||
}
|
||||
|
||||
std::cout << "\r" << spaces << "\r";
|
||||
std::print("\r{}\r", spaces);
|
||||
|
||||
std::string message = "";
|
||||
|
||||
@@ -74,7 +76,7 @@ void CProgressBar::print() {
|
||||
message += " " + std::format("{} / {}", m_iSteps, m_iMaxSteps) + " ";
|
||||
|
||||
// draw message
|
||||
std::cout << message + " " + m_szCurrentMessage;
|
||||
std::print("{} {}", message, m_szCurrentMessage);
|
||||
|
||||
std::fflush(stdout);
|
||||
}
|
60
meson.build
@@ -1,13 +1,17 @@
|
||||
project('Hyprland', 'cpp', 'c',
|
||||
version : run_command('cat', join_paths(meson.source_root(), 'VERSION'), 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(
|
||||
@@ -16,16 +20,28 @@ add_project_arguments(
|
||||
'-Wno-unused-value',
|
||||
'-Wno-missing-field-initializers',
|
||||
'-Wno-narrowing',
|
||||
'-Wno-pointer-arith',
|
||||
datarootdir,
|
||||
'-Wno-pointer-arith', datarootdir,
|
||||
'-DHYPRLAND_VERSION="' + meson.project_version() + '"',
|
||||
],
|
||||
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
|
||||
|
||||
aquamarine = dependency('aquamarine', version: '>=0.4.5')
|
||||
hyprcursor = dependency('hyprcursor', version: '>=0.1.7')
|
||||
hyprgraphics = dependency('hyprgraphics', version: '>= 0.1.1')
|
||||
hyprlang = dependency('hyprlang', version: '>= 0.3.2')
|
||||
hyprutils = dependency('hyprutils', version: '>= 0.2.3')
|
||||
add_project_arguments(['-DAQUAMARINE_VERSION="@0@"'.format(aquamarine.version())], language: 'cpp')
|
||||
add_project_arguments(['-DHYPRCURSOR_VERSION="@0@"'.format(hyprcursor.version())], language: 'cpp')
|
||||
add_project_arguments(['-DHYPRGRAPHICS_VERSION="@0@"'.format(hyprgraphics.version())], language: 'cpp')
|
||||
add_project_arguments(['-DHYPRLANG_VERSION="@0@"'.format(hyprlang.version())], language: 'cpp')
|
||||
add_project_arguments(['-DHYPRUTILS_VERSION="@0@"'.format(hyprutils.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,9 +50,7 @@ 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 not xcb_dep.found()
|
||||
add_project_arguments('-DNO_XWAYLAND', language: 'cpp')
|
||||
@@ -45,8 +59,17 @@ endif
|
||||
backtrace_dep = cpp_compiler.find_library('execinfo', required: false)
|
||||
epoll_dep = dependency('epoll-shim', required: false) # timerfd on BSDs
|
||||
|
||||
if get_option('systemd').enabled()
|
||||
re2 = dependency('re2', required: true)
|
||||
|
||||
# Handle options
|
||||
systemd_option = get_option('systemd')
|
||||
systemd = dependency('systemd', required: systemd_option)
|
||||
systemd_option.enable_auto_if(systemd.found())
|
||||
|
||||
if (systemd_option.enabled())
|
||||
message('Enabling systemd integration')
|
||||
add_project_arguments('-DUSES_SYSTEMD', language: 'cpp')
|
||||
subdir('systemd')
|
||||
endif
|
||||
|
||||
if get_option('legacy_renderer').enabled()
|
||||
@@ -57,14 +80,24 @@ 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')
|
||||
@@ -73,6 +106,7 @@ subdir('assets')
|
||||
subdir('example')
|
||||
subdir('docs')
|
||||
|
||||
# Generate hyprland.pc
|
||||
pkg_install_dir = join_paths(get_option('datadir'), 'pkgconfig')
|
||||
|
||||
import('pkgconfig').generate(
|
||||
|
@@ -1,3 +1,5 @@
|
||||
option('xwayland', type: 'feature', value: 'auto', description: 'Enable support for X11 applications')
|
||||
option('systemd', type: 'feature', value: 'auto', description: 'Enable systemd integration')
|
||||
option('uwsm', type: 'feature', value: 'enabled', description: 'Enable uwsm integration (only if systemd is enabled)')
|
||||
option('legacy_renderer', type: 'feature', value: 'disabled', description: 'Enable legacy renderer')
|
||||
option('tracy_enable', type: 'boolean', value: false , description: 'Enable profiling')
|
||||
|
131
nix/default.nix
@@ -1,43 +1,36 @@
|
||||
{
|
||||
lib,
|
||||
stdenv,
|
||||
stdenvAdapters,
|
||||
pkg-config,
|
||||
pkgconf,
|
||||
makeWrapper,
|
||||
cmake,
|
||||
meson,
|
||||
ninja,
|
||||
aquamarine,
|
||||
binutils,
|
||||
cairo,
|
||||
expat,
|
||||
fribidi,
|
||||
git,
|
||||
hwdata,
|
||||
hyprcursor,
|
||||
hyprgraphics,
|
||||
hyprland-protocols,
|
||||
hyprland-qtutils,
|
||||
hyprlang,
|
||||
hyprutils,
|
||||
hyprwayland-scanner,
|
||||
jq,
|
||||
libGL,
|
||||
libdatrie,
|
||||
libdisplay-info,
|
||||
libdrm,
|
||||
libexecinfo,
|
||||
libinput,
|
||||
libliftoff,
|
||||
libselinux,
|
||||
libsepol,
|
||||
libthai,
|
||||
libuuid,
|
||||
libxkbcommon,
|
||||
libuuid,
|
||||
mesa,
|
||||
pango,
|
||||
pciutils,
|
||||
pcre2,
|
||||
python3,
|
||||
seatd,
|
||||
re2,
|
||||
systemd,
|
||||
tomlplusplus,
|
||||
udis86-hyprland,
|
||||
wayland,
|
||||
wayland-protocols,
|
||||
wayland-scanner,
|
||||
@@ -50,25 +43,40 @@
|
||||
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
|
||||
(lib.optional debug stdenvAdapters.keepDebugInfo)
|
||||
];
|
||||
|
||||
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 (finalAttrs: {
|
||||
pname = "hyprland${optionalString debug "-debug"}";
|
||||
inherit version;
|
||||
|
||||
src = lib.cleanSourceWith {
|
||||
filter = name: type: let
|
||||
src = cleanSourceWith {
|
||||
filter = name: _type: let
|
||||
baseName = baseNameOf (toString name);
|
||||
in
|
||||
! (lib.hasSuffix ".nix" baseName);
|
||||
src = lib.cleanSource ../.;
|
||||
! (hasSuffix ".nix" baseName);
|
||||
src = cleanSource ../.;
|
||||
};
|
||||
|
||||
postPatch = ''
|
||||
@@ -79,20 +87,22 @@ assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been remov
|
||||
sed -i "s#@PREFIX@/##g" hyprland.pc.in
|
||||
'';
|
||||
|
||||
COMMITS = commit;
|
||||
COMMITS = revCount;
|
||||
DATE = date;
|
||||
DIRTY = lib.optionalString (commit == "") "dirty";
|
||||
DIRTY = optionalString (commit == "") "dirty";
|
||||
HASH = commit;
|
||||
TAG = "v${builtins.readFile "${finalAttrs.src}/VERSION"}";
|
||||
|
||||
depsBuildBuild = [
|
||||
pkg-config
|
||||
];
|
||||
|
||||
nativeBuildInputs = [
|
||||
hyprwayland-scanner
|
||||
jq
|
||||
makeWrapper
|
||||
cmake
|
||||
meson
|
||||
ninja
|
||||
pkg-config
|
||||
python3 # for udis86
|
||||
wayland-scanner
|
||||
];
|
||||
|
||||
outputs = [
|
||||
@@ -101,70 +111,67 @@ assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been remov
|
||||
"dev"
|
||||
];
|
||||
|
||||
buildInputs = lib.concatLists [
|
||||
buildInputs = concatLists [
|
||||
[
|
||||
aquamarine
|
||||
cairo
|
||||
expat
|
||||
fribidi
|
||||
git
|
||||
hwdata
|
||||
hyprcursor
|
||||
hyprgraphics
|
||||
hyprland-protocols
|
||||
hyprlang
|
||||
hyprutils
|
||||
libdatrie
|
||||
libdisplay-info
|
||||
libdrm
|
||||
libGL
|
||||
libinput
|
||||
libliftoff
|
||||
libselinux
|
||||
libsepol
|
||||
libthai
|
||||
libuuid
|
||||
libxkbcommon
|
||||
mesa
|
||||
pango
|
||||
pciutils
|
||||
pcre2
|
||||
seatd
|
||||
re2
|
||||
tomlplusplus
|
||||
udis86-hyprland
|
||||
wayland
|
||||
wayland-protocols
|
||||
]
|
||||
(lib.optionals stdenv.hostPlatform.isMusl [libexecinfo])
|
||||
(lib.optionals enableXWayland [
|
||||
xorg.libxcb
|
||||
wayland-scanner
|
||||
xorg.libXcursor
|
||||
]
|
||||
(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";
|
||||
|
||||
# we want as much debug info as possible
|
||||
dontStrip = debug;
|
||||
|
||||
cmakeFlags = [
|
||||
(lib.cmakeBool "NO_XWAYLAND" (!enableXWayland))
|
||||
(lib.cmakeBool "LEGACY_RENDERER" legacyRenderer)
|
||||
(lib.cmakeBool "NO_SYSTEMD" (!withSystemd))
|
||||
mesonFlags = flatten [
|
||||
(mapAttrsToList mesonEnable {
|
||||
"xwayland" = enableXWayland;
|
||||
"legacy_renderer" = legacyRenderer;
|
||||
"uwsm" = false;
|
||||
})
|
||||
(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
|
||||
hyprland-qtutils
|
||||
pciutils
|
||||
pkgconf
|
||||
]}
|
||||
@@ -180,4 +187,4 @@ assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been remov
|
||||
platforms = lib.platforms.linux;
|
||||
mainProgram = "Hyprland";
|
||||
};
|
||||
}
|
||||
})
|
||||
|
64
nix/formatter.nix
Normal file
@@ -0,0 +1,64 @@
|
||||
{
|
||||
writeShellApplication,
|
||||
deadnix,
|
||||
statix,
|
||||
alejandra,
|
||||
llvmPackages_19,
|
||||
fd,
|
||||
}:
|
||||
writeShellApplication {
|
||||
name = "hyprland-treewide-formatter";
|
||||
runtimeInputs = [
|
||||
deadnix
|
||||
statix
|
||||
alejandra
|
||||
llvmPackages_19.clang-tools
|
||||
fd
|
||||
];
|
||||
text = ''
|
||||
# shellcheck disable=SC2148
|
||||
|
||||
# common excludes
|
||||
excludes="subprojects"
|
||||
|
||||
nix_format() {
|
||||
if [ "$*" = 0 ]; then
|
||||
fd '.*\.nix' . -E "$excludes" -x statix fix -- {} \;
|
||||
fd '.*\.nix' . -E "$excludes" -X deadnix -e -- {} \; -X alejandra {} \;
|
||||
elif [ -d "$1" ]; then
|
||||
fd '.*\.nix' "$1" -E "$excludes" -i -x statix fix -- {} \;
|
||||
fd '.*\.nix' "$1" -E "$excludes" -i -X deadnix -e -- {} \; -X alejandra {} \;
|
||||
else
|
||||
statix fix -- "$1"
|
||||
deadnix -e "$1"
|
||||
alejandra "$1"
|
||||
fi
|
||||
}
|
||||
|
||||
cpp_format() {
|
||||
if [ "$*" = 0 ] || [ "$1" = "." ]; then
|
||||
fd '.*\.cpp' . -E "$excludes" | xargs clang-format --verbose -i
|
||||
elif [ -d "$1" ]; then
|
||||
fd '.*\.cpp' "$1" -E "$excludes" | xargs clang-format --verbose -i
|
||||
else
|
||||
clang-format --verbose -i "$1"
|
||||
fi
|
||||
}
|
||||
|
||||
for i in "$@"; do
|
||||
case ''${i##*.} in
|
||||
"nix")
|
||||
nix_format "$i"
|
||||
;;
|
||||
"cpp")
|
||||
cpp_format "$i"
|
||||
;;
|
||||
*)
|
||||
nix_format "$i"
|
||||
cpp_format "$i"
|
||||
;;
|
||||
esac
|
||||
|
||||
done
|
||||
'';
|
||||
}
|
@@ -22,22 +22,33 @@ in {
|
||||
# Dependencies
|
||||
inputs.aquamarine.overlays.default
|
||||
inputs.hyprcursor.overlays.default
|
||||
inputs.hyprgraphics.overlays.default
|
||||
inputs.hyprland-protocols.overlays.default
|
||||
inputs.hyprland-qtutils.overlays.default
|
||||
inputs.hyprlang.overlays.default
|
||||
inputs.hyprutils.overlays.default
|
||||
inputs.hyprwayland-scanner.overlays.default
|
||||
self.overlays.udis86
|
||||
|
||||
# Hyprland packages themselves
|
||||
(final: prev: let
|
||||
(final: _prev: let
|
||||
date = mkDate (self.lastModifiedDate or "19700101");
|
||||
in {
|
||||
hyprland = final.callPackage ./default.nix {
|
||||
stdenv = final.gcc13Stdenv;
|
||||
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;};
|
||||
hyprland-debug = final.hyprland.override {debug = true;};
|
||||
|
||||
# Build major libs with debug to get as much info as possible in a stacktrace
|
||||
hyprland-debug = final.hyprland.override {
|
||||
aquamarine = final.aquamarine.override {debug = true;};
|
||||
hyprutils = final.hyprutils.override {debug = true;};
|
||||
debug = true;
|
||||
};
|
||||
hyprland-legacy-renderer = final.hyprland.override {legacyRenderer = true;};
|
||||
|
||||
# deprecated packages
|
||||
@@ -60,6 +71,22 @@ in {
|
||||
# Packages for extra software recommended for usage with Hyprland,
|
||||
# including forked or patched packages for compatibility.
|
||||
hyprland-extras = lib.composeManyExtensions [
|
||||
inputs.xdph.overlays.xdg-desktop-portal-hyprland
|
||||
inputs.xdph.overlays.default
|
||||
];
|
||||
|
||||
# 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,76 +1,78 @@
|
||||
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',
|
||||
version: '>=0.2',
|
||||
hyprland_protos = dependency(
|
||||
'hyprland-protocols',
|
||||
version: '>=0.4',
|
||||
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')
|
||||
|
||||
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,
|
||||
)
|
||||
|
||||
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'],
|
||||
['wlr-screencopy-unstable-v1.xml'],
|
||||
[hl_protocol_dir, 'protocols/hyprland-global-shortcuts-v1.xml'],
|
||||
[hl_protocol_dir, 'protocols/hyprland-toplevel-export-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/text-input/text-input-unstable-v1.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_protocol_dir, 'staging/drm-lease/drm-lease-v1.xml'],
|
||||
[wl_protocol_dir, 'staging/linux-drm-syncobj/linux-drm-syncobj-v1.xml'],
|
||||
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',
|
||||
'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',
|
||||
hyprland_protocol_dir / 'protocols/hyprland-ctm-control-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',
|
||||
wayland_protocol_dir / 'staging/security-context/security-context-v1.xml',
|
||||
]
|
||||
|
||||
wl_protos_src = []
|
||||
wl_protos_headers = []
|
||||
|
||||
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'],
|
||||
@@ -78,31 +80,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,
|
||||
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)
|
||||
|
@@ -1,7 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <deque>
|
||||
#include <list>
|
||||
#include <sys/resource.h>
|
||||
|
||||
@@ -35,7 +34,7 @@
|
||||
|
||||
class CWLSurfaceResource;
|
||||
|
||||
enum eManagersInitStage {
|
||||
enum eManagersInitStage : uint8_t {
|
||||
STAGE_PRIORITY = 0,
|
||||
STAGE_BASICINIT,
|
||||
STAGE_LATE
|
||||
@@ -59,15 +58,15 @@ class CCompositor {
|
||||
std::string m_szInstancePath = "";
|
||||
std::string m_szCurrentSplash = "error";
|
||||
|
||||
std::vector<SP<CMonitor>> m_vMonitors;
|
||||
std::vector<SP<CMonitor>> m_vRealMonitors; // for all monitors, even those turned off
|
||||
std::vector<PHLMONITOR> m_vMonitors;
|
||||
std::vector<PHLMONITOR> m_vRealMonitors; // for all monitors, even those turned off
|
||||
std::vector<PHLWINDOW> m_vWindows;
|
||||
std::vector<PHLLS> m_vLayers;
|
||||
std::vector<PHLWORKSPACE> m_vWorkspaces;
|
||||
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(std::string socketName, int socketFd);
|
||||
void startCompositor();
|
||||
@@ -80,7 +79,7 @@ class CCompositor {
|
||||
|
||||
WP<CWLSurfaceResource> m_pLastFocus;
|
||||
PHLWINDOWREF m_pLastWindow;
|
||||
WP<CMonitor> m_pLastMonitor;
|
||||
PHLMONITORREF m_pLastMonitor;
|
||||
|
||||
std::vector<PHLWINDOWREF> m_vWindowFocusHistory; // first element is the most recently focused.
|
||||
|
||||
@@ -89,71 +88,63 @@ class CCompositor {
|
||||
bool m_bDPMSStateON = true;
|
||||
bool m_bUnsafeState = false; // unsafe state is when there is no monitors.
|
||||
bool m_bNextIsUnsafe = false;
|
||||
CMonitor* m_pUnsafeOutput = nullptr; // fallback output for the unsafe state
|
||||
PHLMONITORREF m_pUnsafeOutput; // fallback output for the unsafe state
|
||||
bool m_bIsShuttingDown = false;
|
||||
bool m_bFinalRequests = false;
|
||||
bool m_bDesktopEnvSet = false;
|
||||
bool m_bEnableXwayland = true;
|
||||
|
||||
// ------------------------------------------------- //
|
||||
|
||||
CMonitor* getMonitorFromID(const int&);
|
||||
CMonitor* getMonitorFromName(const std::string&);
|
||||
CMonitor* getMonitorFromDesc(const std::string&);
|
||||
CMonitor* getMonitorFromCursor();
|
||||
CMonitor* getMonitorFromVector(const Vector2D&);
|
||||
PHLMONITOR getMonitorFromID(const MONITORID&);
|
||||
PHLMONITOR getMonitorFromName(const std::string&);
|
||||
PHLMONITOR getMonitorFromDesc(const std::string&);
|
||||
PHLMONITOR getMonitorFromCursor();
|
||||
PHLMONITOR getMonitorFromVector(const Vector2D&);
|
||||
void removeWindowFromVectorSafe(PHLWINDOW);
|
||||
void focusWindow(PHLWINDOW, SP<CWLSurfaceResource> pSurface = nullptr);
|
||||
void focusSurface(SP<CWLSurfaceResource>, PHLWINDOW pWindowOwner = nullptr);
|
||||
bool monitorExists(CMonitor*);
|
||||
bool monitorExists(PHLMONITOR);
|
||||
PHLWINDOW vectorToWindowUnified(const Vector2D&, uint8_t properties, PHLWINDOW pIgnoreWindow = nullptr);
|
||||
SP<CWLSurfaceResource> vectorToLayerSurface(const Vector2D&, std::vector<PHLLSREF>*, Vector2D*, PHLLS*);
|
||||
SP<CWLSurfaceResource> vectorToLayerPopupSurface(const Vector2D&, CMonitor* monitor, Vector2D*, PHLLS*);
|
||||
SP<CWLSurfaceResource> vectorToLayerPopupSurface(const Vector2D&, PHLMONITOR monitor, Vector2D*, PHLLS*);
|
||||
SP<CWLSurfaceResource> vectorWindowToSurface(const Vector2D&, PHLWINDOW, Vector2D& sl);
|
||||
Vector2D vectorToSurfaceLocal(const Vector2D&, PHLWINDOW, SP<CWLSurfaceResource>);
|
||||
CMonitor* getMonitorFromOutput(SP<Aquamarine::IOutput>);
|
||||
CMonitor* getRealMonitorFromOutput(SP<Aquamarine::IOutput>);
|
||||
PHLMONITOR getMonitorFromOutput(SP<Aquamarine::IOutput>);
|
||||
PHLMONITOR getRealMonitorFromOutput(SP<Aquamarine::IOutput>);
|
||||
PHLWINDOW getWindowFromSurface(SP<CWLSurfaceResource>);
|
||||
PHLWINDOW getWindowFromHandle(uint32_t);
|
||||
bool isWorkspaceVisible(PHLWORKSPACE);
|
||||
bool isWorkspaceVisibleNotCovered(PHLWORKSPACE);
|
||||
PHLWORKSPACE getWorkspaceByID(const int&);
|
||||
PHLWORKSPACE getWorkspaceByID(const WORKSPACEID&);
|
||||
PHLWORKSPACE getWorkspaceByName(const std::string&);
|
||||
PHLWORKSPACE getWorkspaceByString(const std::string&);
|
||||
void sanityCheckWorkspaces();
|
||||
void updateWorkspaceWindowDecos(const int&);
|
||||
void updateWorkspaceWindowData(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 = {});
|
||||
PHLWINDOW getUrgentWindow();
|
||||
bool hasUrgentWindowOnWorkspace(const int&);
|
||||
PHLWINDOW getFirstWindowOnWorkspace(const int&);
|
||||
PHLWINDOW getTopLeftWindowOnWorkspace(const int&);
|
||||
PHLWINDOW getFullscreenWindowOnWorkspace(const int&);
|
||||
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&);
|
||||
bool isPointOnReservedArea(const Vector2D& point, const PHLMONITOR monitor = nullptr);
|
||||
PHLMONITOR getMonitorInDirection(const char&);
|
||||
PHLMONITOR getMonitorInDirection(PHLMONITOR, const char&);
|
||||
void updateAllWindowsAnimatedDecorationValues();
|
||||
void updateWorkspaceWindows(const int64_t& id);
|
||||
void updateWindowAnimatedDecorationValues(PHLWINDOW);
|
||||
int 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&);
|
||||
MONITORID getNextAvailableMonitorID(std::string const& name);
|
||||
void moveWorkspaceToMonitor(PHLWORKSPACE, PHLMONITOR, bool noWarpCursor = false);
|
||||
void swapActiveWorkspaces(PHLMONITOR, PHLMONITOR);
|
||||
PHLMONITOR getMonitorFromString(const std::string&);
|
||||
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 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*, Aquamarine::IOutput::scheduleFrameReason reason = Aquamarine::IOutput::AQ_SCHEDULE_CLIENT_UNKNOWN);
|
||||
void scheduleFrameForMonitor(PHLMONITOR, Aquamarine::IOutput::scheduleFrameReason reason = Aquamarine::IOutput::AQ_SCHEDULE_CLIENT_UNKNOWN);
|
||||
void addToFadingOutSafe(PHLLS);
|
||||
void removeFromFadingOutSafe(PHLLS);
|
||||
void addToFadingOutSafe(PHLWINDOW);
|
||||
@@ -162,12 +153,11 @@ class CCompositor {
|
||||
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 setActiveMonitor(CMonitor*);
|
||||
bool isWorkspaceSpecial(const int&);
|
||||
int getNewSpecialID();
|
||||
PHLWORKSPACE createNewWorkspace(const WORKSPACEID&, const MONITORID&, const std::string& name = "",
|
||||
bool isEmpty = true); // will be deleted next frame if left empty and unfocused!
|
||||
void setActiveMonitor(PHLMONITOR);
|
||||
bool isWorkspaceSpecial(const WORKSPACEID&);
|
||||
WORKSPACEID getNewSpecialID();
|
||||
void performUserChecks();
|
||||
void moveWindowToWorkspaceSafe(PHLWINDOW pWindow, PHLWORKSPACE pWorkspace);
|
||||
PHLWINDOW getForceFocus();
|
||||
|
@@ -5,9 +5,7 @@
|
||||
#include <any>
|
||||
#include <hyprutils/math/Box.hpp>
|
||||
|
||||
using namespace Hyprutils::Math;
|
||||
|
||||
enum eIcons {
|
||||
enum eIcons : uint8_t {
|
||||
ICON_WARNING = 0,
|
||||
ICON_INFO,
|
||||
ICON_HINT,
|
||||
@@ -17,7 +15,7 @@ enum eIcons {
|
||||
ICON_NONE
|
||||
};
|
||||
|
||||
enum eRenderStage {
|
||||
enum eRenderStage : uint8_t {
|
||||
RENDER_PRE = 0, /* Before binding the gl context */
|
||||
RENDER_BEGIN, /* Just when the rendering begins, nothing has been rendered yet. Damage, current render data in opengl valid. */
|
||||
RENDER_PRE_WINDOWS, /* Pre windows, post bottom and overlay layers */
|
||||
@@ -29,7 +27,7 @@ enum eRenderStage {
|
||||
RENDER_POST_WINDOW, /* After rendering a window (any pass) */
|
||||
};
|
||||
|
||||
enum eInputType {
|
||||
enum eInputType : uint8_t {
|
||||
INPUT_TYPE_AXIS = 0,
|
||||
INPUT_TYPE_BUTTON,
|
||||
INPUT_TYPE_DRAG_START,
|
||||
@@ -41,7 +39,7 @@ struct SCallbackInfo {
|
||||
bool cancelled = false; /* on cancellable events, will cancel the event. */
|
||||
};
|
||||
|
||||
enum eHyprCtlOutputFormat {
|
||||
enum eHyprCtlOutputFormat : uint8_t {
|
||||
FORMAT_NORMAL = 0,
|
||||
FORMAT_JSON
|
||||
};
|
||||
@@ -52,4 +50,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;
|
||||
|
@@ -3,7 +3,7 @@
|
||||
#include "../helpers/varlist/VarList.hpp"
|
||||
#include <vector>
|
||||
|
||||
enum eConfigValueDataTypes {
|
||||
enum eConfigValueDataTypes : int8_t {
|
||||
CVD_TYPE_INVALID = -1,
|
||||
CVD_TYPE_GRADIENT = 0,
|
||||
CVD_TYPE_CSS_VALUE = 1
|
||||
@@ -20,24 +20,40 @@ class ICustomConfigValueData {
|
||||
|
||||
class CGradientValueData : public ICustomConfigValueData {
|
||||
public:
|
||||
CGradientValueData() {};
|
||||
CGradientValueData(CColor col) {
|
||||
CGradientValueData() = default;
|
||||
CGradientValueData(CHyprColor col) {
|
||||
m_vColors.push_back(col);
|
||||
updateColorsOk();
|
||||
};
|
||||
virtual ~CGradientValueData() {};
|
||||
virtual ~CGradientValueData() = default;
|
||||
|
||||
virtual eConfigValueDataTypes getDataType() {
|
||||
return CVD_TYPE_GRADIENT;
|
||||
}
|
||||
|
||||
void reset(CColor col) {
|
||||
void reset(CHyprColor col) {
|
||||
m_vColors.clear();
|
||||
m_vColors.emplace_back(col);
|
||||
m_fAngle = 0;
|
||||
updateColorsOk();
|
||||
}
|
||||
|
||||
void updateColorsOk() {
|
||||
m_vColorsOkLabA.clear();
|
||||
for (auto& c : m_vColors) {
|
||||
const auto OKLAB = c.asOkLab();
|
||||
m_vColorsOkLabA.emplace_back(OKLAB.l);
|
||||
m_vColorsOkLabA.emplace_back(OKLAB.a);
|
||||
m_vColorsOkLabA.emplace_back(OKLAB.b);
|
||||
m_vColorsOkLabA.emplace_back(c.a);
|
||||
}
|
||||
}
|
||||
|
||||
/* Vector containing the colors */
|
||||
std::vector<CColor> m_vColors;
|
||||
std::vector<CHyprColor> m_vColors;
|
||||
|
||||
/* Vector containing pure colors for shoving into opengl */
|
||||
std::vector<float> m_vColorsOkLabA;
|
||||
|
||||
/* Float corresponding to the angle (rad) */
|
||||
float m_fAngle = 0;
|
||||
|
1631
src/config/ConfigDescriptions.hpp
Normal file
@@ -6,10 +6,9 @@
|
||||
#include "../debug/Log.hpp"
|
||||
#include <unordered_map>
|
||||
#include "../defines.hpp"
|
||||
#include <variant>
|
||||
#include <vector>
|
||||
#include <deque>
|
||||
#include <algorithm>
|
||||
#include <regex>
|
||||
#include <optional>
|
||||
#include <functional>
|
||||
#include <xf86drmMode.h>
|
||||
@@ -33,7 +32,7 @@ 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;
|
||||
@@ -68,13 +67,13 @@ struct SAnimationPropertyConfig {
|
||||
};
|
||||
|
||||
struct SPluginKeyword {
|
||||
HANDLE handle = 0;
|
||||
HANDLE handle = nullptr;
|
||||
std::string name = "";
|
||||
Hyprlang::PCONFIGHANDLERFUNC fn = nullptr;
|
||||
};
|
||||
|
||||
struct SPluginVariable {
|
||||
HANDLE handle = 0;
|
||||
HANDLE handle = nullptr;
|
||||
std::string name = "";
|
||||
};
|
||||
|
||||
@@ -83,6 +82,70 @@ struct SExecRequestedRule {
|
||||
uint64_t iPid = 0;
|
||||
};
|
||||
|
||||
enum eConfigOptionType : uint8_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 : uint8_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 {
|
||||
CHyprColor 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();
|
||||
@@ -102,18 +165,20 @@ class CConfigManager {
|
||||
Hyprlang::CConfigValue* getHyprlangConfigValuePtr(const std::string& name, const std::string& specialCat = "");
|
||||
void onPluginLoadUnload(const std::string& name, bool load);
|
||||
static std::string getMainConfigPath();
|
||||
const std::string getConfigString();
|
||||
std::string getConfigString();
|
||||
|
||||
SMonitorRule getMonitorRuleFor(const CMonitor&);
|
||||
SMonitorRule getMonitorRuleFor(const PHLMONITOR);
|
||||
SWorkspaceRule getWorkspaceRuleFor(PHLWORKSPACE workspace);
|
||||
std::string getDefaultWorkspaceFor(const std::string&);
|
||||
|
||||
CMonitor* getBoundMonitorForWS(const std::string&);
|
||||
PHLMONITOR getBoundMonitorForWS(const std::string&);
|
||||
std::string getBoundMonitorStringForWS(const std::string&);
|
||||
const std::deque<SWorkspaceRule>& getAllWorkspaceRules();
|
||||
const std::vector<SWorkspaceRule>& getAllWorkspaceRules();
|
||||
|
||||
std::vector<SWindowRule> getMatchingRules(PHLWINDOW, bool dynamic = true, bool shadowExec = false);
|
||||
std::vector<SLayerRule> getMatchingRules(PHLLS);
|
||||
std::vector<SP<CWindowRule>> getMatchingRules(PHLWINDOW, bool dynamic = true, bool shadowExec = false);
|
||||
std::vector<SP<CLayerRule>> getMatchingRules(PHLLS);
|
||||
|
||||
const std::vector<SConfigOptionDescription>& getAllDescriptions();
|
||||
|
||||
std::unordered_map<std::string, SMonitorAdditionalReservedArea> m_mAdditionalReservedAreas;
|
||||
|
||||
@@ -125,12 +190,15 @@ class CConfigManager {
|
||||
|
||||
// no-op when done.
|
||||
void dispatchExecOnce();
|
||||
void dispatchExecShutdown();
|
||||
|
||||
void performMonitorReload();
|
||||
void appendMonitorRule(const SMonitorRule&);
|
||||
bool replaceMonitorRule(const SMonitorRule&);
|
||||
void ensureMonitorStatus();
|
||||
void ensureVRR(CMonitor* pMonitor = nullptr);
|
||||
void ensureVRR(PHLMONITOR pMonitor = nullptr);
|
||||
|
||||
bool shouldUseSoftwareCursors();
|
||||
|
||||
std::string parseKeyword(const std::string&, const std::string&);
|
||||
|
||||
@@ -146,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&);
|
||||
@@ -164,31 +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<bool>*(const PHLWINDOW&)>> mbWindowProperties = {
|
||||
{"allowsinput", [](const PHLWINDOW& pWindow) { return &pWindow->m_sWindowData.allowsInput; }},
|
||||
{"dimaround", [](const PHLWINDOW& pWindow) { return &pWindow->m_sWindowData.dimAround; }},
|
||||
{"decorate", [](const PHLWINDOW& pWindow) { return &pWindow->m_sWindowData.decorate; }},
|
||||
{"focusonactivate", [](const PHLWINDOW& pWindow) { return &pWindow->m_sWindowData.focusOnActivate; }},
|
||||
{"keepaspectratio", [](const PHLWINDOW& pWindow) { return &pWindow->m_sWindowData.keepAspectRatio; }},
|
||||
{"nearestneighbor", [](const PHLWINDOW& pWindow) { return &pWindow->m_sWindowData.nearestNeighbor; }},
|
||||
{"noanim", [](const PHLWINDOW& pWindow) { return &pWindow->m_sWindowData.noAnim; }},
|
||||
{"noblur", [](const PHLWINDOW& pWindow) { return &pWindow->m_sWindowData.noBlur; }},
|
||||
{"noborder", [](const PHLWINDOW& pWindow) { return &pWindow->m_sWindowData.noBorder; }},
|
||||
{"nodim", [](const PHLWINDOW& pWindow) { return &pWindow->m_sWindowData.noDim; }},
|
||||
{"nofocus", [](const PHLWINDOW& pWindow) { return &pWindow->m_sWindowData.noFocus; }},
|
||||
{"nomaxsize", [](const PHLWINDOW& pWindow) { return &pWindow->m_sWindowData.noMaxSize; }},
|
||||
{"norounding", [](const PHLWINDOW& pWindow) { return &pWindow->m_sWindowData.noRounding; }},
|
||||
{"noshadow", [](const PHLWINDOW& pWindow) { return &pWindow->m_sWindowData.noShadow; }},
|
||||
{"noshortcutsinhibit", [](const PHLWINDOW& pWindow) { return &pWindow->m_sWindowData.noShortcutsInhibit; }},
|
||||
{"opaque", [](const PHLWINDOW& pWindow) { return &pWindow->m_sWindowData.opaque; }},
|
||||
{"forcergbx", [](const PHLWINDOW& pWindow) { return &pWindow->m_sWindowData.RGBX; }},
|
||||
{"syncfullscreen", [](const PHLWINDOW& pWindow) { return &pWindow->m_sWindowData.syncFullscreen; }},
|
||||
{"immediate", [](const PHLWINDOW& pWindow) { return &pWindow->m_sWindowData.tearing; }},
|
||||
{"xray", [](const 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; }}};
|
||||
std::unordered_map<std::string, std::function<CWindowOverridableVar<int>*(const PHLWINDOW&)>> miWindowProperties = {
|
||||
{"rounding", [](const PHLWINDOW& pWindow) { return &pWindow->m_sWindowData.rounding; }},
|
||||
{"bordersize", [](const PHLWINDOW& pWindow) { return &pWindow->m_sWindowData.borderSize; }},
|
||||
};
|
||||
|
||||
std::unordered_map<std::string, std::function<CWindowOverridableVar<float>*(PHLWINDOW)>> mfWindowProperties = {
|
||||
{"scrollmouse", [](const PHLWINDOW& pWindow) { return &pWindow->m_sWindowData.scrollMouse; }},
|
||||
{"scrolltouchpad", [](const PHLWINDOW& pWindow) { return &pWindow->m_sWindowData.scrollTouchpad; }}};
|
||||
|
||||
bool m_bWantsMonitorReload = false;
|
||||
bool m_bForceReload = false;
|
||||
@@ -198,7 +273,7 @@ class CConfigManager {
|
||||
private:
|
||||
std::unique_ptr<Hyprlang::CConfig> m_pConfig;
|
||||
|
||||
std::deque<std::string> configPaths; // stores all the config paths
|
||||
std::vector<std::string> configPaths; // stores all the config paths
|
||||
std::unordered_map<std::string, time_t> configModifyTimes; // stores modify times
|
||||
|
||||
std::unordered_map<std::string, SAnimationPropertyConfig> animationConfig; // stores all the animations with their set values
|
||||
@@ -213,15 +288,16 @@ class CConfigManager {
|
||||
|
||||
bool isFirstLaunch = true; // For exec-once
|
||||
|
||||
std::deque<SMonitorRule> m_dMonitorRules;
|
||||
std::deque<SWorkspaceRule> m_dWorkspaceRules;
|
||||
std::deque<SWindowRule> m_dWindowRules;
|
||||
std::deque<SLayerRule> m_dLayerRules;
|
||||
std::deque<std::string> m_dBlurLSNamespaces;
|
||||
std::vector<SMonitorRule> m_vMonitorRules;
|
||||
std::vector<SWorkspaceRule> m_vWorkspaceRules;
|
||||
std::vector<SP<CWindowRule>> m_vWindowRules;
|
||||
std::vector<SP<CLayerRule>> m_vLayerRules;
|
||||
std::vector<std::string> m_dBlurLSNamespaces;
|
||||
|
||||
bool firstExecDispatched = false;
|
||||
bool m_bManualCrashInitiated = false;
|
||||
std::deque<std::string> firstExecRequests;
|
||||
std::vector<std::string> firstExecRequests;
|
||||
std::vector<std::string> finalExecRequests;
|
||||
|
||||
std::vector<std::pair<std::string, std::string>> m_vFailedPluginConfigValues; // for plugin values of unloaded plugins
|
||||
std::string m_szConfigErrors = "";
|
||||
|
@@ -13,6 +13,7 @@ class CConfigValue {
|
||||
CConfigValue(const std::string& val) {
|
||||
const auto PVHYPRLANG = g_pConfigManager->getHyprlangConfigValuePtr(val);
|
||||
|
||||
// NOLINTNEXTLINE
|
||||
p_ = PVHYPRLANG->getDataStaticPtr();
|
||||
|
||||
#ifdef HYPRLAND_DEBUG
|
||||
|
@@ -4,8 +4,8 @@
|
||||
|
||||
inline const std::string AUTOCONFIG = R"#(
|
||||
# #######################################################################################
|
||||
# AUTOGENERATED HYPR CONFIG.
|
||||
# PLEASE USE THE CONFIG PROVIDED IN THE GIT REPO /examples/hypr.conf AND EDIT IT,
|
||||
# AUTOGENERATED HYPRLAND CONFIG.
|
||||
# PLEASE USE THE CONFIG PROVIDED IN THE GIT REPO /examples/hyprland.conf AND EDIT IT,
|
||||
# OR EDIT THIS ONE ACCORDING TO THE WIKI INSTRUCTIONS.
|
||||
# #######################################################################################
|
||||
|
||||
@@ -13,7 +13,7 @@ autogenerated = 1 # remove this line to remove the warning
|
||||
|
||||
# This is an example Hyprland config file.
|
||||
# Refer to the wiki for more information.
|
||||
# https://wiki.hyprland.org/Configuring/Configuring-Hyprland/
|
||||
# https://wiki.hyprland.org/Configuring/
|
||||
|
||||
# Please note not all available settings / options are set here.
|
||||
# For a full list, see the wiki
|
||||
@@ -99,10 +99,12 @@ decoration {
|
||||
active_opacity = 1.0
|
||||
inactive_opacity = 1.0
|
||||
|
||||
drop_shadow = true
|
||||
shadow_range = 4
|
||||
shadow_render_power = 3
|
||||
col.shadow = rgba(1a1a1aee)
|
||||
shadow {
|
||||
enabled = true
|
||||
range = 4
|
||||
render_power = 3
|
||||
color = rgba(1a1a1aee)
|
||||
}
|
||||
|
||||
# https://wiki.hyprland.org/Configuring/Variables/#blur
|
||||
blur {
|
||||
@@ -116,20 +118,44 @@ decoration {
|
||||
|
||||
# https://wiki.hyprland.org/Configuring/Variables/#animations
|
||||
animations {
|
||||
enabled = true
|
||||
enabled = yes, please :)
|
||||
|
||||
# Default animations, see https://wiki.hyprland.org/Configuring/Animations/ for more
|
||||
|
||||
bezier = myBezier, 0.05, 0.9, 0.1, 1.05
|
||||
bezier = easeOutQuint,0.23,1,0.32,1
|
||||
bezier = easeInOutCubic,0.65,0.05,0.36,1
|
||||
bezier = linear,0,0,1,1
|
||||
bezier = almostLinear,0.5,0.5,0.75,1.0
|
||||
bezier = quick,0.15,0,0.1,1
|
||||
|
||||
animation = windows, 1, 7, myBezier
|
||||
animation = windowsOut, 1, 7, default, popin 80%
|
||||
animation = border, 1, 10, default
|
||||
animation = borderangle, 1, 8, default
|
||||
animation = fade, 1, 7, default
|
||||
animation = workspaces, 1, 6, default
|
||||
animation = global, 1, 10, default
|
||||
animation = border, 1, 5.39, easeOutQuint
|
||||
animation = windows, 1, 4.79, easeOutQuint
|
||||
animation = windowsIn, 1, 4.1, easeOutQuint, popin 87%
|
||||
animation = windowsOut, 1, 1.49, linear, popin 87%
|
||||
animation = fadeIn, 1, 1.73, almostLinear
|
||||
animation = fadeOut, 1, 1.46, almostLinear
|
||||
animation = fade, 1, 3.03, quick
|
||||
animation = layers, 1, 3.81, easeOutQuint
|
||||
animation = layersIn, 1, 4, easeOutQuint, fade
|
||||
animation = layersOut, 1, 1.5, linear, fade
|
||||
animation = fadeLayersIn, 1, 1.79, almostLinear
|
||||
animation = fadeLayersOut, 1, 1.39, almostLinear
|
||||
animation = workspaces, 1, 1.94, almostLinear, fade
|
||||
animation = workspacesIn, 1, 1.21, almostLinear, fade
|
||||
animation = workspacesOut, 1, 1.94, almostLinear, fade
|
||||
}
|
||||
|
||||
# Ref https://wiki.hyprland.org/Configuring/Workspace-Rules/
|
||||
# "Smart gaps" / "No gaps when only"
|
||||
# uncomment all if you wish to use that.
|
||||
# workspace = w[tv1], gapsout:0, gapsin:0
|
||||
# workspace = f[1], gapsout:0, gapsin:0
|
||||
# windowrulev2 = bordersize 0, floating:0, onworkspace:w[tv1]
|
||||
# windowrulev2 = rounding 0, floating:0, onworkspace:w[tv1]
|
||||
# windowrulev2 = bordersize 0, floating:0, onworkspace:f[1]
|
||||
# windowrulev2 = rounding 0, floating:0, onworkspace:f[1]
|
||||
|
||||
# See https://wiki.hyprland.org/Configuring/Dwindle-Layout/ for more
|
||||
dwindle {
|
||||
pseudotile = true # Master switch for pseudotiling. Enabling is bound to mainMod + P in the keybinds section below
|
||||
@@ -182,9 +208,9 @@ device {
|
||||
}
|
||||
|
||||
|
||||
####################
|
||||
### KEYBINDINGSS ###
|
||||
####################
|
||||
###################
|
||||
### KEYBINDINGS ###
|
||||
###################
|
||||
|
||||
# See https://wiki.hyprland.org/Configuring/Keywords/
|
||||
$mainMod = SUPER # Sets "Windows" key as main modifier
|
||||
@@ -241,6 +267,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 +294,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
|
||||
)#";
|
||||
|
@@ -2,8 +2,8 @@
|
||||
#include <fcntl.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <link.h>
|
||||
#include <time.h>
|
||||
#include <errno.h>
|
||||
#include <ctime>
|
||||
#include <cerrno>
|
||||
#include <sys/stat.h>
|
||||
#include <filesystem>
|
||||
|
||||
@@ -31,10 +31,10 @@ static char const* const MESSAGES[] = {"Sorry, didn't mean to...",
|
||||
|
||||
// <random> is not async-signal-safe, fake it with time(NULL) instead
|
||||
char const* getRandomMessage() {
|
||||
return MESSAGES[time(NULL) % (sizeof(MESSAGES) / sizeof(MESSAGES[0]))];
|
||||
return MESSAGES[time(nullptr) % (sizeof(MESSAGES) / sizeof(MESSAGES[0]))];
|
||||
}
|
||||
|
||||
[[noreturn]] inline void exit_with_error(char const* err) {
|
||||
[[noreturn]] inline void exitWithError(char const* err) {
|
||||
write(STDERR_FILENO, err, strlen(err));
|
||||
// perror() is not signal-safe, but we use it here
|
||||
// because if the crash-handler already crashed, it can't get any worse.
|
||||
@@ -42,17 +42,17 @@ char const* getRandomMessage() {
|
||||
abort();
|
||||
}
|
||||
|
||||
void CrashReporter::createAndSaveCrash(int sig) {
|
||||
int reportFd;
|
||||
void NCrashReporter::createAndSaveCrash(int sig) {
|
||||
int reportFd = -1;
|
||||
|
||||
// We're in the signal handler, so we *only* have stack memory.
|
||||
// To save as much stack memory as possible,
|
||||
// destroy things as soon as possible.
|
||||
{
|
||||
MaxLengthCString<255> reportPath;
|
||||
CMaxLengthCString<255> reportPath;
|
||||
|
||||
const auto HOME = sig_getenv("HOME");
|
||||
const auto CACHE_HOME = sig_getenv("XDG_CACHE_HOME");
|
||||
const auto HOME = sigGetenv("HOME");
|
||||
const auto CACHE_HOME = sigGetenv("XDG_CACHE_HOME");
|
||||
|
||||
if (CACHE_HOME && CACHE_HOME[0] != '\0') {
|
||||
reportPath += CACHE_HOME;
|
||||
@@ -61,24 +61,24 @@ void CrashReporter::createAndSaveCrash(int sig) {
|
||||
reportPath += HOME;
|
||||
reportPath += "/.cache/hyprland";
|
||||
} else {
|
||||
exit_with_error("$CACHE_HOME and $HOME not set, nowhere to report crash\n");
|
||||
exitWithError("$CACHE_HOME and $HOME not set, nowhere to report crash\n");
|
||||
return;
|
||||
}
|
||||
|
||||
int ret = mkdir(reportPath.get_str(), S_IRWXU);
|
||||
int ret = mkdir(reportPath.getStr(), S_IRWXU);
|
||||
//__asm__("int $3");
|
||||
if (ret < 0 && errno != EEXIST) {
|
||||
exit_with_error("failed to mkdir() crash report directory\n");
|
||||
exitWithError("failed to mkdir() crash report directory\n");
|
||||
}
|
||||
reportPath += "/hyprlandCrashReport";
|
||||
reportPath.write_num(getpid());
|
||||
reportPath.writeNum(getpid());
|
||||
reportPath += ".txt";
|
||||
|
||||
{
|
||||
BufFileWriter<64> stderr(2);
|
||||
CBufFileWriter<64> stderr(2);
|
||||
stderr += "Hyprland has crashed :( Consult the crash report at ";
|
||||
if (!reportPath.boundsExceeded()) {
|
||||
stderr += reportPath.get_str();
|
||||
stderr += reportPath.getStr();
|
||||
} else {
|
||||
stderr += "[ERROR: Crash report path does not fit into memory! Check if your $CACHE_HOME/$HOME is too deeply nested. Max 255 characters.]";
|
||||
}
|
||||
@@ -86,12 +86,12 @@ void CrashReporter::createAndSaveCrash(int sig) {
|
||||
stderr.flush();
|
||||
}
|
||||
|
||||
reportFd = open(reportPath.get_str(), O_WRONLY | O_CREAT, S_IRWXU);
|
||||
reportFd = open(reportPath.getStr(), O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
|
||||
if (reportFd < 0) {
|
||||
exit_with_error("Failed to open crash report path for writing");
|
||||
exitWithError("Failed to open crash report path for writing");
|
||||
}
|
||||
}
|
||||
BufFileWriter<512> finalCrashReport(reportFd);
|
||||
CBufFileWriter<512> finalCrashReport(reportFd);
|
||||
|
||||
finalCrashReport += "--------------------------------------------\n Hyprland Crash Report\n--------------------------------------------\n";
|
||||
finalCrashReport += getRandomMessage();
|
||||
@@ -100,7 +100,7 @@ void CrashReporter::createAndSaveCrash(int sig) {
|
||||
finalCrashReport += "Hyprland received signal ";
|
||||
finalCrashReport.writeNum(sig);
|
||||
finalCrashReport += '(';
|
||||
finalCrashReport += sig_strsignal(sig);
|
||||
finalCrashReport += sigStrsignal(sig);
|
||||
finalCrashReport += ")\nVersion: ";
|
||||
finalCrashReport += GIT_COMMIT_HASH;
|
||||
finalCrashReport += "\nTag: ";
|
||||
@@ -122,9 +122,9 @@ void CrashReporter::createAndSaveCrash(int sig) {
|
||||
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";
|
||||
|
||||
size_t count = g_pPluginSystem->pluginCount();
|
||||
CPlugin* plugins[count];
|
||||
g_pPluginSystem->sig_getPlugins(plugins, count);
|
||||
const size_t count = g_pPluginSystem->pluginCount();
|
||||
std::vector<CPlugin*> plugins(count);
|
||||
g_pPluginSystem->sigGetPlugins(plugins.data(), count);
|
||||
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
auto p = plugins[i];
|
||||
@@ -159,7 +159,7 @@ void CrashReporter::createAndSaveCrash(int sig) {
|
||||
|
||||
finalCrashReport += "GPU:\n\t";
|
||||
#if defined(__DragonFly__) || defined(__FreeBSD__)
|
||||
finalCrashReport.writeCmdOutput("pciconf -lv | fgrep -A4 vga");
|
||||
finalCrashReport.writeCmdOutput("pciconf -lv | grep -F -A4 vga");
|
||||
#else
|
||||
finalCrashReport.writeCmdOutput("lspci -vnn | grep VGA");
|
||||
#endif
|
||||
@@ -241,5 +241,5 @@ void CrashReporter::createAndSaveCrash(int sig) {
|
||||
|
||||
finalCrashReport += "\n\nLog tail:\n";
|
||||
|
||||
finalCrashReport += std::string_view(Debug::rollingLog).substr(Debug::rollingLog.find("\n") + 1);
|
||||
finalCrashReport += std::string_view(Debug::rollingLog).substr(Debug::rollingLog.find('\n') + 1);
|
||||
}
|
||||
|
@@ -2,6 +2,6 @@
|
||||
|
||||
#include "../defines.hpp"
|
||||
|
||||
namespace CrashReporter {
|
||||
namespace NCrashReporter {
|
||||
void createAndSaveCrash(int sig);
|
||||
};
|
@@ -5,6 +5,10 @@
|
||||
#include "../helpers/MiscFunctions.hpp"
|
||||
#include <functional>
|
||||
|
||||
// exposed for main.cpp
|
||||
std::string systemInfoRequest(eHyprCtlOutputFormat format, std::string request);
|
||||
std::string versionRequest(eHyprCtlOutputFormat format, std::string request);
|
||||
|
||||
class CHyprCtl {
|
||||
public:
|
||||
CHyprCtl();
|
||||
|
@@ -7,8 +7,13 @@ CHyprDebugOverlay::CHyprDebugOverlay() {
|
||||
m_pTexture = makeShared<CTexture>();
|
||||
}
|
||||
|
||||
void CHyprMonitorDebugOverlay::renderData(CMonitor* pMonitor, float µs) {
|
||||
m_dLastRenderTimes.push_back(µs / 1000.f);
|
||||
void CHyprMonitorDebugOverlay::renderData(PHLMONITOR pMonitor, float durationUs) {
|
||||
static auto PDEBUGOVERLAY = CConfigValue<Hyprlang::INT>("debug:overlay");
|
||||
|
||||
if (!*PDEBUGOVERLAY)
|
||||
return;
|
||||
|
||||
m_dLastRenderTimes.emplace_back(durationUs / 1000.f);
|
||||
|
||||
if (m_dLastRenderTimes.size() > (long unsigned int)pMonitor->refreshRate)
|
||||
m_dLastRenderTimes.pop_front();
|
||||
@@ -17,8 +22,13 @@ 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(PHLMONITOR pMonitor, float durationUs) {
|
||||
static auto PDEBUGOVERLAY = CConfigValue<Hyprlang::INT>("debug:overlay");
|
||||
|
||||
if (!*PDEBUGOVERLAY)
|
||||
return;
|
||||
|
||||
m_dLastRenderTimesNoOverlay.emplace_back(durationUs / 1000.f);
|
||||
|
||||
if (m_dLastRenderTimesNoOverlay.size() > (long unsigned int)pMonitor->refreshRate)
|
||||
m_dLastRenderTimesNoOverlay.pop_front();
|
||||
@@ -27,8 +37,13 @@ void CHyprMonitorDebugOverlay::renderDataNoOverlay(CMonitor* pMonitor, float µs
|
||||
m_pMonitor = pMonitor;
|
||||
}
|
||||
|
||||
void CHyprMonitorDebugOverlay::frameData(CMonitor* pMonitor) {
|
||||
m_dLastFrametimes.push_back(std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now() - m_tpLastFrame).count() / 1000.f);
|
||||
void CHyprMonitorDebugOverlay::frameData(PHLMONITOR pMonitor) {
|
||||
static auto PDEBUGOVERLAY = CConfigValue<Hyprlang::INT>("debug:overlay");
|
||||
|
||||
if (!*PDEBUGOVERLAY)
|
||||
return;
|
||||
|
||||
m_dLastFrametimes.emplace_back(std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now() - m_tpLastFrame).count() / 1000.f);
|
||||
|
||||
if (m_dLastFrametimes.size() > (long unsigned int)pMonitor->refreshRate)
|
||||
m_dLastFrametimes.pop_front();
|
||||
@@ -39,7 +54,7 @@ void CHyprMonitorDebugOverlay::frameData(CMonitor* pMonitor) {
|
||||
m_pMonitor = pMonitor;
|
||||
|
||||
// anim data too
|
||||
const auto PMONITORFORTICKS = g_pHyprRenderer->m_pMostHzMonitor ? g_pHyprRenderer->m_pMostHzMonitor : g_pCompositor->m_pLastMonitor.get();
|
||||
const auto PMONITORFORTICKS = g_pHyprRenderer->m_pMostHzMonitor ? g_pHyprRenderer->m_pMostHzMonitor.lock() : g_pCompositor->m_pLastMonitor.lock();
|
||||
if (PMONITORFORTICKS) {
|
||||
if (m_dLastAnimationTicks.size() > (long unsigned int)PMONITORFORTICKS->refreshRate)
|
||||
m_dLastAnimationTicks.pop_front();
|
||||
@@ -57,7 +72,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 +85,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 +98,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 +111,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,21 +203,36 @@ int CHyprMonitorDebugOverlay::draw(int offset) {
|
||||
return posY - offset;
|
||||
}
|
||||
|
||||
void CHyprDebugOverlay::renderData(CMonitor* pMonitor, float µs) {
|
||||
m_mMonitorOverlays[pMonitor].renderData(pMonitor, µs);
|
||||
void CHyprDebugOverlay::renderData(PHLMONITOR pMonitor, float durationUs) {
|
||||
static auto PDEBUGOVERLAY = CConfigValue<Hyprlang::INT>("debug:overlay");
|
||||
|
||||
if (!*PDEBUGOVERLAY)
|
||||
return;
|
||||
|
||||
m_mMonitorOverlays[pMonitor].renderData(pMonitor, durationUs);
|
||||
}
|
||||
|
||||
void CHyprDebugOverlay::renderDataNoOverlay(CMonitor* pMonitor, float µs) {
|
||||
m_mMonitorOverlays[pMonitor].renderDataNoOverlay(pMonitor, µs);
|
||||
void CHyprDebugOverlay::renderDataNoOverlay(PHLMONITOR pMonitor, float durationUs) {
|
||||
static auto PDEBUGOVERLAY = CConfigValue<Hyprlang::INT>("debug:overlay");
|
||||
|
||||
if (!*PDEBUGOVERLAY)
|
||||
return;
|
||||
|
||||
m_mMonitorOverlays[pMonitor].renderDataNoOverlay(pMonitor, durationUs);
|
||||
}
|
||||
|
||||
void CHyprDebugOverlay::frameData(CMonitor* pMonitor) {
|
||||
void CHyprDebugOverlay::frameData(PHLMONITOR pMonitor) {
|
||||
static auto PDEBUGOVERLAY = CConfigValue<Hyprlang::INT>("debug:overlay");
|
||||
|
||||
if (!*PDEBUGOVERLAY)
|
||||
return;
|
||||
|
||||
m_mMonitorOverlays[pMonitor].frameData(pMonitor);
|
||||
}
|
||||
|
||||
void CHyprDebugOverlay::draw() {
|
||||
|
||||
const auto PMONITOR = g_pCompositor->m_vMonitors.front().get();
|
||||
const auto PMONITOR = g_pCompositor->m_vMonitors.front();
|
||||
|
||||
if (!m_pCairoSurface || !m_pCairo) {
|
||||
m_pCairoSurface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y);
|
||||
@@ -217,8 +247,8 @@ void CHyprDebugOverlay::draw() {
|
||||
|
||||
// draw the things
|
||||
int offsetY = 0;
|
||||
for (auto& m : g_pCompositor->m_vMonitors) {
|
||||
offsetY += m_mMonitorOverlays[m.get()].draw(offsetY);
|
||||
for (auto const& m : g_pCompositor->m_vMonitors) {
|
||||
offsetY += m_mMonitorOverlays[m].draw(offsetY);
|
||||
offsetY += 5; // for padding between mons
|
||||
}
|
||||
|
||||
|
@@ -3,9 +3,9 @@
|
||||
#include "../defines.hpp"
|
||||
#include "../helpers/Monitor.hpp"
|
||||
#include "../render/Texture.hpp"
|
||||
#include <deque>
|
||||
#include <cairo/cairo.h>
|
||||
#include <unordered_map>
|
||||
#include <map>
|
||||
#include <deque>
|
||||
|
||||
class CHyprRenderer;
|
||||
|
||||
@@ -13,9 +13,9 @@ class CHyprMonitorDebugOverlay {
|
||||
public:
|
||||
int draw(int offset);
|
||||
|
||||
void renderData(CMonitor* pMonitor, float µs);
|
||||
void renderDataNoOverlay(CMonitor* pMonitor, float µs);
|
||||
void frameData(CMonitor* pMonitor);
|
||||
void renderData(PHLMONITOR pMonitor, float durationUs);
|
||||
void renderDataNoOverlay(PHLMONITOR pMonitor, float durationUs);
|
||||
void frameData(PHLMONITOR pMonitor);
|
||||
|
||||
private:
|
||||
std::deque<float> m_dLastFrametimes;
|
||||
@@ -23,7 +23,7 @@ class CHyprMonitorDebugOverlay {
|
||||
std::deque<float> m_dLastRenderTimesNoOverlay;
|
||||
std::deque<float> m_dLastAnimationTicks;
|
||||
std::chrono::high_resolution_clock::time_point m_tpLastFrame;
|
||||
CMonitor* m_pMonitor = nullptr;
|
||||
PHLMONITORREF m_pMonitor;
|
||||
CBox m_wbLastDrawnBox;
|
||||
|
||||
friend class CHyprRenderer;
|
||||
@@ -33,12 +33,12 @@ class CHyprDebugOverlay {
|
||||
public:
|
||||
CHyprDebugOverlay();
|
||||
void draw();
|
||||
void renderData(CMonitor*, float µs);
|
||||
void renderDataNoOverlay(CMonitor*, float µs);
|
||||
void frameData(CMonitor*);
|
||||
void renderData(PHLMONITOR, float durationUs);
|
||||
void renderDataNoOverlay(PHLMONITOR, float durationUs);
|
||||
void frameData(PHLMONITOR);
|
||||
|
||||
private:
|
||||
std::unordered_map<CMonitor*, CHyprMonitorDebugOverlay> m_mMonitorOverlays;
|
||||
std::map<PHLMONITORREF, CHyprMonitorDebugOverlay> m_mMonitorOverlays;
|
||||
|
||||
cairo_surface_t* m_pCairoSurface = nullptr;
|
||||
cairo_t* m_pCairo = nullptr;
|
||||
|
@@ -18,7 +18,7 @@ inline auto iconBackendFromLayout(PangoLayout* layout) {
|
||||
|
||||
CHyprNotificationOverlay::CHyprNotificationOverlay() {
|
||||
static auto P = g_pHookSystem->hookDynamic("focusedMon", [&](void* self, SCallbackInfo& info, std::any param) {
|
||||
if (m_dNotifications.size() == 0)
|
||||
if (m_vNotifications.size() == 0)
|
||||
return;
|
||||
|
||||
g_pHyprRenderer->damageBox(&m_bLastDamage);
|
||||
@@ -34,34 +34,34 @@ CHyprNotificationOverlay::~CHyprNotificationOverlay() {
|
||||
cairo_surface_destroy(m_pCairoSurface);
|
||||
}
|
||||
|
||||
void CHyprNotificationOverlay::addNotification(const std::string& text, const CColor& color, const float timeMs, const eIcons icon, const float fontSize) {
|
||||
const auto PNOTIF = m_dNotifications.emplace_back(std::make_unique<SNotification>()).get();
|
||||
void CHyprNotificationOverlay::addNotification(const std::string& text, const CHyprColor& color, const float timeMs, const eIcons icon, const float fontSize) {
|
||||
const auto PNOTIF = m_vNotifications.emplace_back(std::make_unique<SNotification>()).get();
|
||||
|
||||
PNOTIF->text = text;
|
||||
PNOTIF->color = color == CColor(0) ? ICONS_COLORS[icon] : color;
|
||||
PNOTIF->text = icon != eIcons::ICON_NONE ? " " + text /* tiny bit of padding otherwise icon touches text */ : text;
|
||||
PNOTIF->color = color == CHyprColor(0) ? ICONS_COLORS[icon] : color;
|
||||
PNOTIF->started.reset();
|
||||
PNOTIF->timeMs = timeMs;
|
||||
PNOTIF->icon = icon;
|
||||
PNOTIF->fontSize = fontSize;
|
||||
|
||||
for (auto& m : g_pCompositor->m_vMonitors) {
|
||||
g_pCompositor->scheduleFrameForMonitor(m.get());
|
||||
for (auto const& m : g_pCompositor->m_vMonitors) {
|
||||
g_pCompositor->scheduleFrameForMonitor(m);
|
||||
}
|
||||
}
|
||||
|
||||
void CHyprNotificationOverlay::dismissNotifications(const int amount) {
|
||||
if (amount == -1)
|
||||
m_dNotifications.clear();
|
||||
m_vNotifications.clear();
|
||||
else {
|
||||
const int AMT = std::min(amount, static_cast<int>(m_dNotifications.size()));
|
||||
const int AMT = std::min(amount, static_cast<int>(m_vNotifications.size()));
|
||||
|
||||
for (int i = 0; i < AMT; ++i) {
|
||||
m_dNotifications.pop_front();
|
||||
m_vNotifications.erase(m_vNotifications.begin());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CBox CHyprNotificationOverlay::drawNotifications(CMonitor* pMonitor) {
|
||||
CBox CHyprNotificationOverlay::drawNotifications(PHLMONITOR pMonitor) {
|
||||
static constexpr auto ANIM_DURATION_MS = 600.0;
|
||||
static constexpr auto ANIM_LAG_MS = 100.0;
|
||||
static constexpr auto NOTIF_LEFTBAR_SIZE = 5.0;
|
||||
@@ -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_vNotifications) {
|
||||
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);
|
||||
|
||||
@@ -182,12 +182,12 @@ CBox CHyprNotificationOverlay::drawNotifications(CMonitor* pMonitor) {
|
||||
g_object_unref(layout);
|
||||
|
||||
// cleanup notifs
|
||||
std::erase_if(m_dNotifications, [](const auto& notif) { return notif->started.getMillis() > notif->timeMs; });
|
||||
std::erase_if(m_vNotifications, [](const auto& notif) { return notif->started.getMillis() > notif->timeMs; });
|
||||
|
||||
return CBox{(int)(pMonitor->vecPosition.x + pMonitor->vecSize.x - maxWidth - 20), (int)pMonitor->vecPosition.y, (int)maxWidth + 20, (int)offsetY + 10};
|
||||
}
|
||||
|
||||
void CHyprNotificationOverlay::draw(CMonitor* pMonitor) {
|
||||
void CHyprNotificationOverlay::draw(PHLMONITOR pMonitor) {
|
||||
|
||||
const auto MONSIZE = pMonitor->vecTransformedSize;
|
||||
|
||||
@@ -205,7 +205,7 @@ void CHyprNotificationOverlay::draw(CMonitor* pMonitor) {
|
||||
}
|
||||
|
||||
// Draw the notifications
|
||||
if (m_dNotifications.size() == 0)
|
||||
if (m_vNotifications.size() == 0)
|
||||
return;
|
||||
|
||||
// Render to the monitor
|
||||
@@ -246,5 +246,5 @@ void CHyprNotificationOverlay::draw(CMonitor* pMonitor) {
|
||||
}
|
||||
|
||||
bool CHyprNotificationOverlay::hasAny() {
|
||||
return !m_dNotifications.empty();
|
||||
return !m_vNotifications.empty();
|
||||
}
|
||||
|
@@ -6,11 +6,11 @@
|
||||
#include "../render/Texture.hpp"
|
||||
#include "../SharedDefs.hpp"
|
||||
|
||||
#include <deque>
|
||||
#include <vector>
|
||||
|
||||
#include <cairo/cairo.h>
|
||||
|
||||
enum eIconBackend {
|
||||
enum eIconBackend : uint8_t {
|
||||
ICONS_BACKEND_NONE = 0,
|
||||
ICONS_BACKEND_NF,
|
||||
ICONS_BACKEND_FA
|
||||
@@ -19,17 +19,17 @@ enum eIconBackend {
|
||||
static const std::array<std::array<std::string, ICON_NONE + 1>, 3 /* backends */> ICONS_ARRAY = {
|
||||
std::array<std::string, ICON_NONE + 1>{"[!]", "[i]", "[Hint]", "[Err]", "[?]", "[ok]", ""},
|
||||
std::array<std::string, ICON_NONE + 1>{"", "", "", "", "", "", ""}, std::array<std::string, ICON_NONE + 1>{"", "", "", "", "", ""}};
|
||||
static const std::array<CColor, ICON_NONE + 1> ICONS_COLORS = {CColor{255.0 / 255.0, 204 / 255.0, 102 / 255.0, 1.0},
|
||||
CColor{128 / 255.0, 255 / 255.0, 255 / 255.0, 1.0},
|
||||
CColor{179 / 255.0, 255 / 255.0, 204 / 255.0, 1.0},
|
||||
CColor{255 / 255.0, 77 / 255.0, 77 / 255.0, 1.0},
|
||||
CColor{255 / 255.0, 204 / 255.0, 153 / 255.0, 1.0},
|
||||
CColor{128 / 255.0, 255 / 255.0, 128 / 255.0, 1.0},
|
||||
CColor{0, 0, 0, 1.0}};
|
||||
static const std::array<CHyprColor, ICON_NONE + 1> ICONS_COLORS = {CHyprColor{255.0 / 255.0, 204 / 255.0, 102 / 255.0, 1.0},
|
||||
CHyprColor{128 / 255.0, 255 / 255.0, 255 / 255.0, 1.0},
|
||||
CHyprColor{179 / 255.0, 255 / 255.0, 204 / 255.0, 1.0},
|
||||
CHyprColor{255 / 255.0, 77 / 255.0, 77 / 255.0, 1.0},
|
||||
CHyprColor{255 / 255.0, 204 / 255.0, 153 / 255.0, 1.0},
|
||||
CHyprColor{128 / 255.0, 255 / 255.0, 128 / 255.0, 1.0},
|
||||
CHyprColor{0, 0, 0, 1.0}};
|
||||
|
||||
struct SNotification {
|
||||
std::string text = "";
|
||||
CColor color;
|
||||
CHyprColor color;
|
||||
CTimer started;
|
||||
float timeMs = 0;
|
||||
eIcons icon = ICON_NONE;
|
||||
@@ -41,21 +41,21 @@ class CHyprNotificationOverlay {
|
||||
CHyprNotificationOverlay();
|
||||
~CHyprNotificationOverlay();
|
||||
|
||||
void draw(CMonitor* pMonitor);
|
||||
void addNotification(const std::string& text, const CColor& color, const float timeMs, const eIcons icon = ICON_NONE, const float fontSize = 13.f);
|
||||
void draw(PHLMONITOR pMonitor);
|
||||
void addNotification(const std::string& text, const CHyprColor& color, const float timeMs, const eIcons icon = ICON_NONE, const float fontSize = 13.f);
|
||||
void dismissNotifications(const int amount);
|
||||
bool hasAny();
|
||||
|
||||
private:
|
||||
CBox drawNotifications(CMonitor* pMonitor);
|
||||
CBox drawNotifications(PHLMONITOR pMonitor);
|
||||
CBox m_bLastDamage;
|
||||
|
||||
std::deque<std::unique_ptr<SNotification>> m_dNotifications;
|
||||
std::vector<std::unique_ptr<SNotification>> m_vNotifications;
|
||||
|
||||
cairo_surface_t* m_pCairoSurface = nullptr;
|
||||
cairo_t* m_pCairo = nullptr;
|
||||
|
||||
CMonitor* m_pLastMonitor = nullptr;
|
||||
PHLMONITORREF m_pLastMonitor;
|
||||
Vector2D m_vecLastSize = Vector2D(-1, -1);
|
||||
|
||||
SP<CTexture> m_pTexture;
|
||||
|
@@ -4,18 +4,21 @@
|
||||
#include "RollingLogFollow.hpp"
|
||||
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <print>
|
||||
#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::close() {
|
||||
logOfs.close();
|
||||
}
|
||||
|
||||
void Debug::log(LogLevel level, std::string str) {
|
||||
void Debug::log(eLogLevel level, std::string str) {
|
||||
if (level == TRACE && !trace)
|
||||
return;
|
||||
|
||||
@@ -23,6 +26,7 @@ void Debug::log(LogLevel level, std::string str) {
|
||||
return;
|
||||
|
||||
std::string coloredStr = str;
|
||||
//NOLINTBEGIN
|
||||
switch (level) {
|
||||
case LOG:
|
||||
str = "[LOG] " + str;
|
||||
@@ -50,13 +54,14 @@ void Debug::log(LogLevel level, std::string str) {
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
//NOLINTEND
|
||||
|
||||
rollingLog += str + "\n";
|
||||
if (rollingLog.size() > ROLLING_LOG_SIZE)
|
||||
rollingLog = rollingLog.substr(rollingLog.size() - ROLLING_LOG_SIZE);
|
||||
|
||||
if (RollingLogFollow::Get().IsRunning())
|
||||
RollingLogFollow::Get().AddLog(str);
|
||||
if (SRollingLogFollow::get().isRunning())
|
||||
SRollingLogFollow::get().addLog(str);
|
||||
|
||||
if (!disableLogs || !**disableLogs) {
|
||||
// log to a file
|
||||
@@ -66,5 +71,5 @@ void Debug::log(LogLevel level, std::string str) {
|
||||
|
||||
// log it to the stdout too.
|
||||
if (!disableStdout)
|
||||
std::cout << ((coloredLogs && !**coloredLogs) ? str : coloredStr) << "\n";
|
||||
std::println("{}", ((coloredLogs && !**coloredLogs) ? str : coloredStr));
|
||||
}
|
||||
|
@@ -11,7 +11,7 @@
|
||||
#define LOGMESSAGESIZE 1024
|
||||
#define ROLLING_LOG_SIZE 4096
|
||||
|
||||
enum LogLevel {
|
||||
enum eLogLevel : int8_t {
|
||||
NONE = -1,
|
||||
LOG = 0,
|
||||
WARN,
|
||||
@@ -21,6 +21,7 @@ enum LogLevel {
|
||||
TRACE
|
||||
};
|
||||
|
||||
// NOLINTNEXTLINE(readability-identifier-naming)
|
||||
namespace Debug {
|
||||
inline std::string logFile;
|
||||
inline std::ofstream logOfs;
|
||||
@@ -38,10 +39,11 @@ namespace Debug {
|
||||
void close();
|
||||
|
||||
//
|
||||
void log(LogLevel level, std::string str);
|
||||
void log(eLogLevel level, std::string str);
|
||||
|
||||
template <typename... Args>
|
||||
void log(LogLevel level, std::format_string<Args...> fmt, Args&&... args) {
|
||||
//NOLINTNEXTLINE
|
||||
void log(eLogLevel level, std::format_string<Args...> fmt, Args&&... args) {
|
||||
std::lock_guard<std::mutex> guard(logMutex);
|
||||
|
||||
if (level == TRACE && !trace)
|
||||
@@ -55,7 +57,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
|
||||
|
@@ -2,8 +2,9 @@
|
||||
|
||||
#include <shared_mutex>
|
||||
|
||||
// NOLINTNEXTLINE(readability-identifier-naming)
|
||||
namespace Debug {
|
||||
struct RollingLogFollow {
|
||||
struct SRollingLogFollow {
|
||||
std::unordered_map<int, std::string> socketToRollingLogFollowQueue;
|
||||
std::shared_mutex m;
|
||||
bool running = false;
|
||||
@@ -15,12 +16,12 @@ namespace Debug {
|
||||
return socketToRollingLogFollowQueue[socket].empty();
|
||||
}
|
||||
|
||||
std::string DebugInfo() {
|
||||
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::string getLog(int socket) {
|
||||
std::unique_lock<std::shared_mutex> w(m);
|
||||
|
||||
const std::string ret = socketToRollingLogFollowQueue[socket];
|
||||
@@ -29,7 +30,7 @@ namespace Debug {
|
||||
return ret;
|
||||
};
|
||||
|
||||
void AddLog(std::string log) {
|
||||
void addLog(const std::string& log) {
|
||||
std::unique_lock<std::shared_mutex> w(m);
|
||||
running = true;
|
||||
std::vector<int> to_erase;
|
||||
@@ -37,26 +38,26 @@ namespace Debug {
|
||||
socketToRollingLogFollowQueue[p.first] += log + "\n";
|
||||
}
|
||||
|
||||
bool IsRunning() {
|
||||
bool isRunning() {
|
||||
std::shared_lock<std::shared_mutex> r(m);
|
||||
return running;
|
||||
}
|
||||
|
||||
void StopFor(int socket) {
|
||||
void stopFor(int socket) {
|
||||
std::unique_lock<std::shared_mutex> w(m);
|
||||
socketToRollingLogFollowQueue.erase(socket);
|
||||
if (socketToRollingLogFollowQueue.empty())
|
||||
running = false;
|
||||
}
|
||||
|
||||
void StartFor(int socket) {
|
||||
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 SRollingLogFollow& get() {
|
||||
static SRollingLogFollow 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"
|
||||
|
@@ -3,6 +3,7 @@
|
||||
class CWorkspace;
|
||||
class CWindow;
|
||||
class CLayerSurface;
|
||||
class CMonitor;
|
||||
|
||||
/* Shared pointer to a workspace */
|
||||
typedef SP<CWorkspace> PHLWORKSPACE;
|
||||
@@ -18,3 +19,8 @@ typedef WP<CWindow> PHLWINDOWREF;
|
||||
typedef SP<CLayerSurface> PHLLS;
|
||||
/* Weak pointer to a layer surface */
|
||||
typedef WP<CLayerSurface> PHLLSREF;
|
||||
|
||||
/* Shared pointer to a monitor */
|
||||
typedef SP<CMonitor> PHLMONITOR;
|
||||
/* Weak pointer to a monitor */
|
||||
typedef WP<CMonitor> PHLMONITORREF;
|
||||
|
37
src/desktop/LayerRule.cpp
Normal file
@@ -0,0 +1,37 @@
|
||||
#include "LayerRule.hpp"
|
||||
#include <unordered_set>
|
||||
#include <algorithm>
|
||||
#include "../debug/Log.hpp"
|
||||
|
||||
static const auto RULES = std::unordered_set<std::string>{"noanim", "blur", "blurpopups", "dimaround"};
|
||||
static const auto RULES_PREFIX = std::unordered_set<std::string>{"ignorealpha", "ignorezero", "xray", "animation", "order"};
|
||||
|
||||
CLayerRule::CLayerRule(const std::string& rule_, const std::string& ns_) : targetNamespace(ns_), rule(rule_) {
|
||||
const bool VALID = RULES.contains(rule) || std::any_of(RULES_PREFIX.begin(), RULES_PREFIX.end(), [&rule_](const auto& prefix) { return rule_.starts_with(prefix); });
|
||||
|
||||
if (!VALID)
|
||||
return;
|
||||
|
||||
if (rule == "noanim")
|
||||
ruleType = RULE_NOANIM;
|
||||
else if (rule == "blur")
|
||||
ruleType = RULE_BLUR;
|
||||
else if (rule == "blurpopups")
|
||||
ruleType = RULE_BLURPOPUPS;
|
||||
else if (rule == "dimaround")
|
||||
ruleType = RULE_DIMAROUND;
|
||||
else if (rule.starts_with("ignorealpha"))
|
||||
ruleType = RULE_IGNOREALPHA;
|
||||
else if (rule.starts_with("ignorezero"))
|
||||
ruleType = RULE_IGNOREZERO;
|
||||
else if (rule.starts_with("xray"))
|
||||
ruleType = RULE_XRAY;
|
||||
else if (rule.starts_with("animation"))
|
||||
ruleType = RULE_ANIMATION;
|
||||
else if (rule.starts_with("order"))
|
||||
ruleType = RULE_ORDER;
|
||||
else {
|
||||
Debug::log(ERR, "CLayerRule: didn't match a rule that was found valid?!");
|
||||
ruleType = RULE_INVALID;
|
||||
}
|
||||
}
|
28
src/desktop/LayerRule.hpp
Normal file
@@ -0,0 +1,28 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <cstdint>
|
||||
|
||||
class CLayerRule {
|
||||
public:
|
||||
CLayerRule(const std::string& rule, const std::string& targetNS);
|
||||
|
||||
enum eRuleType : uint8_t {
|
||||
RULE_INVALID = 0,
|
||||
RULE_NOANIM,
|
||||
RULE_BLUR,
|
||||
RULE_BLURPOPUPS,
|
||||
RULE_DIMAROUND,
|
||||
RULE_IGNOREALPHA,
|
||||
RULE_IGNOREZERO,
|
||||
RULE_XRAY,
|
||||
RULE_ANIMATION,
|
||||
RULE_ORDER,
|
||||
RULE_ZUMBA,
|
||||
};
|
||||
|
||||
eRuleType ruleType = RULE_INVALID;
|
||||
|
||||
const std::string targetNamespace;
|
||||
const std::string rule;
|
||||
};
|
@@ -8,7 +8,7 @@
|
||||
PHLLS CLayerSurface::create(SP<CLayerShellResource> resource) {
|
||||
PHLLS pLS = SP<CLayerSurface>(new CLayerSurface(resource));
|
||||
|
||||
CMonitor* pMonitor = resource->monitor.empty() ? g_pCompositor->getMonitorFromCursor() : g_pCompositor->getMonitorFromName(resource->monitor);
|
||||
auto pMonitor = resource->monitor.empty() ? g_pCompositor->m_pLastMonitor.lock() : g_pCompositor->getMonitorFromName(resource->monitor);
|
||||
|
||||
pLS->surface->assign(resource->surface.lock(), pLS);
|
||||
|
||||
@@ -18,7 +18,7 @@ PHLLS CLayerSurface::create(SP<CLayerShellResource> resource) {
|
||||
}
|
||||
|
||||
if (pMonitor->pMirrorOf)
|
||||
pMonitor = g_pCompositor->m_vMonitors.front().get();
|
||||
pMonitor = g_pCompositor->m_vMonitors.front();
|
||||
|
||||
pLS->self = pLS;
|
||||
|
||||
@@ -26,7 +26,7 @@ PHLLS CLayerSurface::create(SP<CLayerShellResource> resource) {
|
||||
|
||||
pLS->layer = resource->current.layer;
|
||||
pLS->popupHead = std::make_unique<CPopup>(pLS);
|
||||
pLS->monitorID = pMonitor->ID;
|
||||
pLS->monitor = pMonitor;
|
||||
pMonitor->m_aLayerSurfaceLayers[resource->current.layer].emplace_back(pLS);
|
||||
|
||||
pLS->forceBlur = g_pConfigManager->shouldBlurLS(pLS->szNamespace);
|
||||
@@ -50,7 +50,7 @@ PHLLS CLayerSurface::create(SP<CLayerShellResource> resource) {
|
||||
void CLayerSurface::registerCallbacks() {
|
||||
alpha.setUpdateCallback([this](void*) {
|
||||
if (dimAround)
|
||||
g_pHyprRenderer->damageMonitor(g_pCompositor->getMonitorFromID(monitorID));
|
||||
g_pHyprRenderer->damageMonitor(monitor.lock());
|
||||
});
|
||||
}
|
||||
|
||||
@@ -71,14 +71,20 @@ 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.get());
|
||||
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(monitorID);
|
||||
const auto PMONITOR = monitor.lock();
|
||||
|
||||
if (!g_pCompositor->getMonitorFromID(monitorID))
|
||||
if (!PMONITOR)
|
||||
Debug::log(WARN, "Layersurface destroyed on an invalid monitor (removed?)");
|
||||
|
||||
if (!fadingOut) {
|
||||
@@ -131,7 +137,7 @@ void CLayerSurface::onMap() {
|
||||
g_pCompositor->removeFromFadingOutSafe(self.lock());
|
||||
|
||||
// fix if it changed its mon
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(monitorID);
|
||||
const auto PMONITOR = monitor.lock();
|
||||
|
||||
if (!PMONITOR)
|
||||
return;
|
||||
@@ -169,8 +175,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 == FSMODE_FULLSCREEN;
|
||||
const bool FULLSCREEN = PMONITOR->activeWorkspace && PMONITOR->activeWorkspace->m_bHasFullscreenWindow && PMONITOR->activeWorkspace->m_efFullscreenMode == FSMODE_FULLSCREEN;
|
||||
|
||||
startAnimation(!(layer == ZWLR_LAYER_SHELL_V1_LAYER_TOP && FULLSCREEN && !GRABSFOCUS));
|
||||
readyToDelete = false;
|
||||
@@ -191,7 +196,7 @@ void CLayerSurface::onUnmap() {
|
||||
|
||||
std::erase_if(g_pInputManager->m_dExclusiveLSes, [this](const auto& other) { return !other.lock() || other.lock() == self.lock(); });
|
||||
|
||||
if (!g_pCompositor->getMonitorFromID(monitorID) || g_pCompositor->m_bUnsafeState) {
|
||||
if (!monitor || g_pCompositor->m_bUnsafeState) {
|
||||
Debug::log(WARN, "Layersurface unmapping on invalid monitor (removed?) ignoring.");
|
||||
|
||||
g_pCompositor->addToFadingOutSafe(self.lock());
|
||||
@@ -215,9 +220,9 @@ void CLayerSurface::onUnmap() {
|
||||
|
||||
g_pCompositor->addToFadingOutSafe(self.lock());
|
||||
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(monitorID);
|
||||
const auto PMONITOR = monitor.lock();
|
||||
|
||||
const bool WASLASTFOCUS = g_pCompositor->m_pLastFocus == surface->resource();
|
||||
const bool WASLASTFOCUS = g_pSeatManager->state.keyboardFocus == surface->resource() || g_pSeatManager->state.pointerFocus == surface->resource();
|
||||
|
||||
if (!PMONITOR)
|
||||
return;
|
||||
@@ -226,7 +231,7 @@ void CLayerSurface::onUnmap() {
|
||||
// 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)
|
||||
else if (g_pCompositor->m_pLastFocus && g_pCompositor->m_pLastFocus != surface->resource())
|
||||
g_pSeatManager->setKeyboardFocus(g_pCompositor->m_pLastFocus.lock());
|
||||
|
||||
CBox geomFixed = {geometry.x + PMONITOR->vecPosition.x, geometry.y + PMONITOR->vecPosition.y, geometry.width, geometry.height};
|
||||
@@ -250,13 +255,13 @@ void CLayerSurface::onCommit() {
|
||||
if (layerSurface->surface && !layerSurface->surface->current.texture) {
|
||||
fadingOut = false;
|
||||
geometry = {};
|
||||
g_pHyprRenderer->arrangeLayersForMonitor(monitorID);
|
||||
g_pHyprRenderer->arrangeLayersForMonitor(monitorID());
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(monitorID);
|
||||
const auto PMONITOR = monitor.lock();
|
||||
|
||||
if (!PMONITOR)
|
||||
return;
|
||||
@@ -315,8 +320,18 @@ void CLayerSurface::onCommit() {
|
||||
realSize.setValueAndWarp(geometry.size());
|
||||
}
|
||||
|
||||
if (mapped) {
|
||||
const bool WASLASTFOCUS = g_pCompositor->m_pLastFocus == surface->resource();
|
||||
if (mapped && (layerSurface->current.committed & CLayerShellResource::eCommittedState::STATE_INTERACTIVITY)) {
|
||||
bool WASLASTFOCUS = false;
|
||||
layerSurface->surface->breadthfirst(
|
||||
[&WASLASTFOCUS](SP<CWLSurfaceResource> surf, const Vector2D& offset, void* data) { WASLASTFOCUS = WASLASTFOCUS || g_pSeatManager->state.keyboardFocus == surf; },
|
||||
nullptr);
|
||||
if (!WASLASTFOCUS && popupHead) {
|
||||
popupHead->breadthfirst(
|
||||
[&WASLASTFOCUS](CPopup* popup, void* data) {
|
||||
WASLASTFOCUS = WASLASTFOCUS || (popup->m_pWLSurface && g_pSeatManager->state.keyboardFocus == popup->m_pWLSurface->resource());
|
||||
},
|
||||
nullptr);
|
||||
}
|
||||
const bool WASEXCLUSIVE = interactivity == ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_EXCLUSIVE;
|
||||
const bool ISEXCLUSIVE = layerSurface->current.interactivity == ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_EXCLUSIVE;
|
||||
|
||||
@@ -326,11 +341,13 @@ void CLayerSurface::onCommit() {
|
||||
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) {
|
||||
if (WASLASTFOCUS && layerSurface->current.interactivity == ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_NONE) {
|
||||
// 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));
|
||||
g_pInputManager->refocusLastWindow(monitor.lock());
|
||||
} else if (WASLASTFOCUS && WASEXCLUSIVE && layerSurface->current.interactivity == ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_ON_DEMAND) {
|
||||
g_pInputManager->simulateMouseMovement();
|
||||
} else if (!WASEXCLUSIVE && ISEXCLUSIVE) {
|
||||
// if now exclusive and not previously
|
||||
g_pSeatManager->setGrab(nullptr);
|
||||
@@ -360,34 +377,58 @@ void CLayerSurface::applyRules() {
|
||||
xray = -1;
|
||||
animationStyle.reset();
|
||||
|
||||
for (auto& rule : g_pConfigManager->getMatchingRules(self.lock())) {
|
||||
if (rule.rule == "noanim")
|
||||
for (auto const& rule : g_pConfigManager->getMatchingRules(self.lock())) {
|
||||
switch (rule->ruleType) {
|
||||
case CLayerRule::RULE_NOANIM: {
|
||||
noAnimations = true;
|
||||
else if (rule.rule == "blur")
|
||||
break;
|
||||
}
|
||||
case CLayerRule::RULE_BLUR: {
|
||||
forceBlur = true;
|
||||
else if (rule.rule == "blurpopups")
|
||||
break;
|
||||
}
|
||||
case CLayerRule::RULE_BLURPOPUPS: {
|
||||
forceBlurPopups = true;
|
||||
else if (rule.rule.starts_with("ignorealpha") || rule.rule.starts_with("ignorezero")) {
|
||||
const auto FIRST_SPACE_POS = rule.rule.find_first_of(' ');
|
||||
break;
|
||||
}
|
||||
case CLayerRule::RULE_IGNOREALPHA:
|
||||
case CLayerRule::RULE_IGNOREZERO: {
|
||||
const auto FIRST_SPACE_POS = rule->rule.find_first_of(' ');
|
||||
std::string alphaValue = "";
|
||||
if (FIRST_SPACE_POS != std::string::npos)
|
||||
alphaValue = rule.rule.substr(FIRST_SPACE_POS + 1);
|
||||
alphaValue = rule->rule.substr(FIRST_SPACE_POS + 1);
|
||||
|
||||
try {
|
||||
ignoreAlpha = true;
|
||||
if (!alphaValue.empty())
|
||||
ignoreAlphaValue = std::stof(alphaValue);
|
||||
} catch (...) { Debug::log(ERR, "Invalid value passed to ignoreAlpha"); }
|
||||
} else if (rule.rule == "dimaround") {
|
||||
break;
|
||||
}
|
||||
case CLayerRule::RULE_DIMAROUND: {
|
||||
dimAround = true;
|
||||
} else if (rule.rule.starts_with("xray")) {
|
||||
CVarList vars{rule.rule, 0, ' '};
|
||||
break;
|
||||
}
|
||||
case CLayerRule::RULE_XRAY: {
|
||||
CVarList vars{rule->rule, 0, ' '};
|
||||
try {
|
||||
xray = configStringToInt(vars[1]);
|
||||
xray = configStringToInt(vars[1]).value_or(false);
|
||||
} catch (...) {}
|
||||
} else if (rule.rule.starts_with("animation")) {
|
||||
CVarList vars{rule.rule, 2, 's'};
|
||||
break;
|
||||
}
|
||||
case CLayerRule::RULE_ANIMATION: {
|
||||
CVarList vars{rule->rule, 2, 's'};
|
||||
animationStyle = vars[1];
|
||||
break;
|
||||
}
|
||||
case CLayerRule::RULE_ORDER: {
|
||||
CVarList vars{rule->rule, 2, 's'};
|
||||
try {
|
||||
order = std::stoi(vars[1]);
|
||||
} catch (...) { Debug::log(ERR, "Invalid value passed to order"); }
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -534,3 +575,7 @@ int CLayerSurface::popupsCount() {
|
||||
popupHead->breadthfirst([](CPopup* p, void* data) { *(int*)data += 1; }, &no);
|
||||
return no;
|
||||
}
|
||||
|
||||
MONITORID CLayerSurface::monitorID() {
|
||||
return monitor ? monitor->ID : MONITOR_INVALID;
|
||||
}
|
||||
|
@@ -4,11 +4,7 @@
|
||||
#include "../defines.hpp"
|
||||
#include "WLSurface.hpp"
|
||||
#include "../helpers/AnimatedVariable.hpp"
|
||||
|
||||
struct SLayerRule {
|
||||
std::string targetNamespace = "";
|
||||
std::string rule = "";
|
||||
};
|
||||
#include "LayerRule.hpp"
|
||||
|
||||
class CLayerShellResource;
|
||||
|
||||
@@ -42,7 +38,7 @@ class CLayerSurface {
|
||||
bool mapped = false;
|
||||
uint32_t layer = 0;
|
||||
|
||||
int monitorID = -1;
|
||||
PHLMONITORREF monitor;
|
||||
|
||||
bool fadingOut = false;
|
||||
bool readyToDelete = false;
|
||||
@@ -51,10 +47,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;
|
||||
|
||||
@@ -69,6 +66,7 @@ class CLayerSurface {
|
||||
void onMap();
|
||||
void onUnmap();
|
||||
void onCommit();
|
||||
MONITORID monitorID();
|
||||
|
||||
private:
|
||||
struct {
|
||||
@@ -82,6 +80,6 @@ class CLayerSurface {
|
||||
|
||||
// For the list lookup
|
||||
bool operator==(const CLayerSurface& rhs) const {
|
||||
return layerSurface == rhs.layerSurface && monitorID == rhs.monitorID;
|
||||
return layerSurface == rhs.layerSurface && monitor == rhs.monitor;
|
||||
}
|
||||
};
|
||||
|
@@ -4,6 +4,8 @@
|
||||
#include "../protocols/LayerShell.hpp"
|
||||
#include "../protocols/XDGShell.hpp"
|
||||
#include "../protocols/core/Compositor.hpp"
|
||||
#include "../managers/SeatManager.hpp"
|
||||
#include "../managers/eventLoop/EventLoopManager.hpp"
|
||||
#include <ranges>
|
||||
|
||||
CPopup::CPopup(PHLWINDOW pOwner) : m_pWindowOwner(pOwner) {
|
||||
@@ -14,13 +16,10 @@ CPopup::CPopup(PHLLS pOwner) : m_pLayerOwner(pOwner) {
|
||||
initAllSignals();
|
||||
}
|
||||
|
||||
CPopup::CPopup(SP<CXDGPopupResource> popup, CPopup* pOwner) : m_pParent(pOwner), m_pResource(popup) {
|
||||
CPopup::CPopup(SP<CXDGPopupResource> popup, CPopup* pOwner) : m_pWindowOwner(pOwner->m_pWindowOwner), m_pLayerOwner(pOwner->m_pLayerOwner), m_pParent(pOwner), m_pResource(popup) {
|
||||
m_pWLSurface = CWLSurface::create();
|
||||
m_pWLSurface->assign(popup->surface->surface.lock(), this);
|
||||
|
||||
m_pLayerOwner = pOwner->m_pLayerOwner;
|
||||
m_pWindowOwner = pOwner->m_pWindowOwner;
|
||||
|
||||
m_vLastSize = popup->surface->current.geometry.size();
|
||||
reposition();
|
||||
|
||||
@@ -106,6 +105,8 @@ void CPopup::onUnmap() {
|
||||
return;
|
||||
}
|
||||
|
||||
m_bMapped = false;
|
||||
|
||||
m_vLastSize = m_pResource->surface->surface->current.size;
|
||||
|
||||
const auto COORDS = coordsGlobal();
|
||||
@@ -116,8 +117,6 @@ void CPopup::onUnmap() {
|
||||
|
||||
m_pSubsurfaceHead.reset();
|
||||
|
||||
g_pInputManager->simulateMouseMovement();
|
||||
|
||||
if (!m_pLayerOwner.expired() && m_pLayerOwner->layer < ZWLR_LAYER_SHELL_V1_LAYER_TOP)
|
||||
g_pHyprOpenGL->markBlurDirtyForMonitor(g_pCompositor->getMonitorFromID(m_pLayerOwner->layer));
|
||||
|
||||
@@ -131,6 +130,11 @@ void CPopup::onUnmap() {
|
||||
g_pHyprRenderer->damageBox(&box);
|
||||
},
|
||||
nullptr);
|
||||
|
||||
const bool WASLASTFOCUS = g_pSeatManager->state.keyboardFocus == m_pWLSurface->resource() || g_pSeatManager->state.pointerFocus == m_pWLSurface->resource();
|
||||
|
||||
if (WASLASTFOCUS)
|
||||
g_pInputManager->simulateMouseMovement();
|
||||
}
|
||||
|
||||
void CPopup::onCommit(bool ignoreSiblings) {
|
||||
@@ -202,6 +206,13 @@ void CPopup::reposition() {
|
||||
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() {
|
||||
Vector2D offset;
|
||||
|
||||
@@ -251,7 +262,7 @@ void CPopup::recheckTree() {
|
||||
|
||||
void CPopup::recheckChildrenRecursive() {
|
||||
auto cpy = m_vChildren;
|
||||
for (auto& c : cpy) {
|
||||
for (auto const& c : cpy) {
|
||||
c->onCommit(true);
|
||||
c->recheckChildrenRecursive();
|
||||
}
|
||||
@@ -281,15 +292,16 @@ bool CPopup::visible() {
|
||||
return false;
|
||||
}
|
||||
|
||||
void CPopup::bfHelper(std::vector<CPopup*> nodes, std::function<void(CPopup*, void*)> fn, void* data) {
|
||||
for (auto& n : nodes) {
|
||||
void CPopup::bfHelper(std::vector<CPopup*> const& nodes, std::function<void(CPopup*, void*)> fn, void* data) {
|
||||
for (auto const& n : nodes) {
|
||||
fn(n, data);
|
||||
}
|
||||
|
||||
std::vector<CPopup*> nodes2;
|
||||
nodes2.reserve(nodes.size() * 2);
|
||||
|
||||
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());
|
||||
}
|
||||
}
|
||||
@@ -308,8 +320,8 @@ 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) {
|
||||
if (!p->m_pResource)
|
||||
for (auto const& p : popups | std::views::reverse) {
|
||||
if (!p->m_pResource || !p->m_bMapped)
|
||||
continue;
|
||||
|
||||
if (!allowsInput) {
|
||||
|
@@ -18,6 +18,7 @@ class CPopup {
|
||||
|
||||
~CPopup();
|
||||
|
||||
SP<CWLSurface> getT1Owner();
|
||||
Vector2D coordsRelativeToParent();
|
||||
Vector2D coordsGlobal();
|
||||
|
||||
@@ -40,6 +41,7 @@ class CPopup {
|
||||
|
||||
//
|
||||
SP<CWLSurface> m_pWLSurface;
|
||||
bool m_bMapped = false;
|
||||
|
||||
private:
|
||||
// T1 owners, each popup has to have one of these
|
||||
@@ -57,7 +59,6 @@ class CPopup {
|
||||
bool m_bRequestedReposition = false;
|
||||
|
||||
bool m_bInert = false;
|
||||
bool m_bMapped = false;
|
||||
|
||||
//
|
||||
std::vector<SP<CPopup>> m_vChildren;
|
||||
@@ -80,5 +81,5 @@ class CPopup {
|
||||
|
||||
Vector2D localToGlobal(const Vector2D& rel);
|
||||
Vector2D t1ParentCoords();
|
||||
static void bfHelper(std::vector<CPopup*> nodes, std::function<void(CPopup*, void*)> fn, void* data);
|
||||
static void bfHelper(std::vector<CPopup*> const& nodes, std::function<void(CPopup*, void*)> fn, void* data);
|
||||
};
|
||||
|
@@ -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;
|
||||
|
@@ -62,7 +62,7 @@ bool CWLSurface::small() const {
|
||||
|
||||
const auto O = m_pWindowOwner.lock();
|
||||
|
||||
return O->m_vReportedSize.x > m_pResource->current.bufferSize.x + 1 || O->m_vReportedSize.y > m_pResource->current.bufferSize.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 {
|
||||
|
@@ -1,3 +1,5 @@
|
||||
#include <re2/re2.h>
|
||||
|
||||
#include <any>
|
||||
#include <bit>
|
||||
#include <string_view>
|
||||
@@ -21,7 +23,6 @@ PHLWINDOW CWindow::create(SP<CXWaylandSurface> 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);
|
||||
@@ -31,6 +32,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));
|
||||
@@ -52,6 +54,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));
|
||||
@@ -112,7 +115,7 @@ SBoxExtents CWindow::getFullWindowExtents() {
|
||||
const int BORDERSIZE = getRealBorderSize();
|
||||
|
||||
if (m_sWindowData.dimAround.valueOrDefault()) {
|
||||
if (const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID); PMONITOR)
|
||||
if (const auto PMONITOR = m_pMonitor.lock(); 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)}};
|
||||
}
|
||||
@@ -172,7 +175,7 @@ SBoxExtents CWindow::getFullWindowExtents() {
|
||||
|
||||
CBox CWindow::getFullWindowBoundingBox() {
|
||||
if (m_sWindowData.dimAround.valueOrDefault()) {
|
||||
if (const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID); PMONITOR)
|
||||
if (const auto PMONITOR = m_pMonitor.lock(); PMONITOR)
|
||||
return {PMONITOR->vecPosition.x, PMONITOR->vecPosition.y, PMONITOR->vecSize.x, PMONITOR->vecSize.y};
|
||||
}
|
||||
|
||||
@@ -185,7 +188,7 @@ CBox CWindow::getFullWindowBoundingBox() {
|
||||
}
|
||||
|
||||
CBox CWindow::getWindowIdealBoundingBoxIgnoreReserved() {
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
|
||||
const auto PMONITOR = m_pMonitor.lock();
|
||||
|
||||
if (!PMONITOR)
|
||||
return {m_vPosition, m_vSize};
|
||||
@@ -220,7 +223,7 @@ CBox CWindow::getWindowIdealBoundingBoxIgnoreReserved() {
|
||||
|
||||
CBox CWindow::getWindowBoxUnified(uint64_t properties) {
|
||||
if (m_sWindowData.dimAround.valueOrDefault()) {
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
|
||||
const auto PMONITOR = m_pMonitor.lock();
|
||||
if (PMONITOR)
|
||||
return {PMONITOR->vecPosition.x, PMONITOR->vecPosition.y, PMONITOR->vecSize.x, PMONITOR->vecSize.y};
|
||||
}
|
||||
@@ -239,10 +242,6 @@ CBox CWindow::getWindowBoxUnified(uint64_t properties) {
|
||||
return box;
|
||||
}
|
||||
|
||||
CBox CWindow::getWindowMainSurfaceBox() {
|
||||
return {m_vRealPosition.value().x, m_vRealPosition.value().y, m_vRealSize.value().x, m_vRealSize.value().y};
|
||||
}
|
||||
|
||||
SBoxExtents CWindow::getFullWindowReservedArea() {
|
||||
return g_pDecorationPositioner->getWindowDecorationReserved(m_pSelf.lock());
|
||||
}
|
||||
@@ -252,7 +251,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());
|
||||
@@ -270,11 +269,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());
|
||||
@@ -296,7 +295,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());
|
||||
}
|
||||
}
|
||||
@@ -305,7 +304,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;
|
||||
|
||||
@@ -337,7 +336,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();
|
||||
}
|
||||
@@ -355,9 +354,9 @@ void CWindow::updateSurfaceScaleTransformDetails(bool force) {
|
||||
|
||||
const auto PLASTMONITOR = g_pCompositor->getMonitorFromID(m_iLastSurfaceMonitorID);
|
||||
|
||||
m_iLastSurfaceMonitorID = m_iMonitorID;
|
||||
m_iLastSurfaceMonitorID = monitorID();
|
||||
|
||||
const auto PNEWMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
|
||||
const auto PNEWMONITOR = m_pMonitor.lock();
|
||||
|
||||
if (!PNEWMONITOR)
|
||||
return;
|
||||
@@ -369,10 +368,10 @@ void CWindow::updateSurfaceScaleTransformDetails(bool force) {
|
||||
m_pWLSurface->resource()->breadthfirst([PNEWMONITOR](SP<CWLSurfaceResource> s, const Vector2D& offset, void* d) { s->enter(PNEWMONITOR->self.lock()); }, nullptr);
|
||||
}
|
||||
|
||||
m_pWLSurface->resource()->breadthfirst(
|
||||
[this](SP<CWLSurfaceResource> s, const Vector2D& offset, void* d) {
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
|
||||
const auto PMONITOR = m_pMonitor.lock();
|
||||
|
||||
m_pWLSurface->resource()->breadthfirst(
|
||||
[PMONITOR](SP<CWLSurfaceResource> s, const Vector2D& offset, void* d) {
|
||||
const auto PSURFACE = CWLSurface::fromResource(s);
|
||||
if (PSURFACE && PSURFACE->m_fLastScale == PMONITOR->scale)
|
||||
return;
|
||||
@@ -407,17 +406,22 @@ void CWindow::moveToWorkspace(PHLWORKSPACE pWorkspace) {
|
||||
|
||||
const auto OLDWORKSPACE = m_pWorkspace;
|
||||
|
||||
m_iMonitorMovedFrom = OLDWORKSPACE ? OLDWORKSPACE->monitorID() : -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->updateWorkspaceWindowData(OLDWORKSPACE->m_iID);
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(OLDWORKSPACE->m_iMonitorID);
|
||||
OLDWORKSPACE->updateWindows();
|
||||
OLDWORKSPACE->updateWindowData();
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(OLDWORKSPACE->monitorID());
|
||||
|
||||
g_pCompositor->updateWorkspaceWindows(workspaceID());
|
||||
g_pCompositor->updateWorkspaceWindowData(workspaceID());
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m_iMonitorID);
|
||||
pWorkspace->updateWindows();
|
||||
pWorkspace->updateWindowData();
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(monitorID());
|
||||
|
||||
g_pCompositor->updateAllWindowsAnimatedDecorationValues();
|
||||
|
||||
@@ -429,32 +433,38 @@ void CWindow::moveToWorkspace(PHLWORKSPACE pWorkspace) {
|
||||
|
||||
if (const auto SWALLOWED = m_pSwallowed.lock()) {
|
||||
SWALLOWED->moveToWorkspace(pWorkspace);
|
||||
SWALLOWED->m_iMonitorID = m_iMonitorID;
|
||||
SWALLOWED->m_pMonitor = m_pMonitor;
|
||||
}
|
||||
|
||||
// update xwayland coords
|
||||
g_pXWaylandManager->setWindowSize(m_pSelf.lock(), m_vRealSize.value());
|
||||
|
||||
if (OLDWORKSPACE && g_pCompositor->isWorkspaceSpecial(OLDWORKSPACE->m_iID) && g_pCompositor->getWindowsOnWorkspace(OLDWORKSPACE->m_iID) == 0 && *PCLOSEONLASTSPECIAL) {
|
||||
if (const auto PMONITOR = g_pCompositor->getMonitorFromID(OLDWORKSPACE->m_iMonitorID); PMONITOR)
|
||||
if (OLDWORKSPACE && g_pCompositor->isWorkspaceSpecial(OLDWORKSPACE->m_iID) && OLDWORKSPACE->getWindows() == 0 && *PCLOSEONLASTSPECIAL) {
|
||||
if (const auto PMONITOR = OLDWORKSPACE->m_pMonitor.lock(); PMONITOR)
|
||||
PMONITOR->setSpecialWorkspace(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
PHLWINDOW CWindow::X11TransientFor() {
|
||||
PHLWINDOW CWindow::x11TransientFor() {
|
||||
if (!m_pXWaylandSurface || !m_pXWaylandSurface->parent)
|
||||
return nullptr;
|
||||
|
||||
auto s = m_pXWaylandSurface->parent;
|
||||
auto oldParent = s;
|
||||
std::vector<SP<CXWaylandSurface>> visited;
|
||||
while (s) {
|
||||
// break cyclic loop of m_pXWaylandSurface being parent of itself, #TODO reject this from even being created?
|
||||
if (!s->parent || s->parent == oldParent)
|
||||
// break loops. Some X apps make them, and it seems like it's valid behavior?!?!?!
|
||||
// TODO: we should reject loops being created in the first place.
|
||||
if (std::find(visited.begin(), visited.end(), s) != visited.end())
|
||||
break;
|
||||
|
||||
visited.emplace_back(s.lock());
|
||||
s = s->parent;
|
||||
}
|
||||
|
||||
for (auto& w : g_pCompositor->m_vWindows) {
|
||||
if (s == m_pXWaylandSurface)
|
||||
return nullptr; // dead-ass circle
|
||||
|
||||
for (auto const& w : g_pCompositor->m_vWindows) {
|
||||
if (w->m_pXWaylandSurface != s)
|
||||
continue;
|
||||
return w;
|
||||
@@ -464,7 +474,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());
|
||||
}
|
||||
@@ -502,25 +512,28 @@ void CWindow::onUnmap() {
|
||||
m_fAlpha.setCallbackOnEnd(unregisterVar);
|
||||
m_cRealShadowColor.setCallbackOnEnd(unregisterVar);
|
||||
m_fDimPercent.setCallbackOnEnd(unregisterVar);
|
||||
m_fMovingToWorkspaceAlpha.setCallbackOnEnd(unregisterVar);
|
||||
|
||||
m_vRealSize.setCallbackOnBegin(nullptr);
|
||||
|
||||
std::erase_if(g_pCompositor->m_vWindowFocusHistory, [&](const auto& other) { return other.expired() || other.lock().get() == this; });
|
||||
|
||||
if (*PCLOSEONLASTSPECIAL && g_pCompositor->getWindowsOnWorkspace(workspaceID()) == 0 && onSpecialWorkspace()) {
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
|
||||
if (*PCLOSEONLASTSPECIAL && m_pWorkspace && m_pWorkspace->getWindows() == 0 && onSpecialWorkspace()) {
|
||||
const auto PMONITOR = m_pMonitor.lock();
|
||||
if (PMONITOR && PMONITOR->activeSpecialWorkspace && PMONITOR->activeSpecialWorkspace == m_pWorkspace)
|
||||
PMONITOR->setSpecialWorkspace(nullptr);
|
||||
}
|
||||
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
|
||||
const auto PMONITOR = m_pMonitor.lock();
|
||||
|
||||
if (PMONITOR && PMONITOR->solitaryClient.lock().get() == this)
|
||||
PMONITOR->solitaryClient.reset();
|
||||
|
||||
g_pCompositor->updateWorkspaceWindows(workspaceID());
|
||||
g_pCompositor->updateWorkspaceWindowData(workspaceID());
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m_iMonitorID);
|
||||
if (m_pWorkspace) {
|
||||
m_pWorkspace->updateWindows();
|
||||
m_pWorkspace->updateWindowData();
|
||||
}
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(monitorID());
|
||||
g_pCompositor->updateAllWindowsAnimatedDecorationValues();
|
||||
|
||||
m_pWorkspace.reset();
|
||||
@@ -542,6 +555,7 @@ void CWindow::onMap() {
|
||||
m_fAlpha.resetAllCallbacks();
|
||||
m_cRealShadowColor.resetAllCallbacks();
|
||||
m_fDimPercent.resetAllCallbacks();
|
||||
m_fMovingToWorkspaceAlpha.resetAllCallbacks();
|
||||
|
||||
m_vRealPosition.registerVar();
|
||||
m_vRealSize.registerVar();
|
||||
@@ -551,6 +565,7 @@ void CWindow::onMap() {
|
||||
m_fAlpha.registerVar();
|
||||
m_cRealShadowColor.registerVar();
|
||||
m_fDimPercent.registerVar();
|
||||
m_fMovingToWorkspaceAlpha.registerVar();
|
||||
|
||||
m_fBorderAngleAnimationProgress.setCallbackOnEnd([&](void* ptr) { onBorderAngleAnimEnd(ptr); }, false);
|
||||
|
||||
@@ -601,23 +616,26 @@ bool CWindow::isHidden() {
|
||||
return m_bHidden;
|
||||
}
|
||||
|
||||
void CWindow::applyDynamicRule(const SWindowRule& r) {
|
||||
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};
|
||||
void CWindow::applyDynamicRule(const SP<CWindowRule>& r) {
|
||||
const eOverridePriority priority = r->execRule ? PRIORITY_SET_PROP : PRIORITY_WINDOW_RULE;
|
||||
|
||||
switch (r->ruleType) {
|
||||
case CWindowRule::RULE_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("opacity")) {
|
||||
Debug::log(ERR, "Tag rule invalid: {}", r->szRule);
|
||||
break;
|
||||
}
|
||||
case CWindowRule::RULE_OPACITY: {
|
||||
try {
|
||||
CVarList vars(r.szRule, 0, ' ');
|
||||
CVarList vars(r->szRule, 0, ' ');
|
||||
|
||||
int opacityIDX = 0;
|
||||
|
||||
for (auto& r : vars) {
|
||||
for (auto const& r : vars) {
|
||||
if (r == "opacity")
|
||||
continue;
|
||||
|
||||
@@ -647,26 +665,30 @@ void CWindow::applyDynamicRule(const SWindowRule& r) {
|
||||
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.starts_with("animation")) {
|
||||
auto STYLE = r.szRule.substr(r.szRule.find_first_of(' ') + 1);
|
||||
} catch (std::exception& e) { Debug::log(ERR, "Opacity rule \"{}\" failed with: {}", r->szRule, e.what()); }
|
||||
break;
|
||||
}
|
||||
case CWindowRule::RULE_ANIMATION: {
|
||||
auto STYLE = r->szRule.substr(r->szRule.find_first_of(' ') + 1);
|
||||
m_sWindowData.animationStyle = CWindowOverridableVar(STYLE, priority);
|
||||
} else if (r.szRule.starts_with("bordercolor")) {
|
||||
break;
|
||||
}
|
||||
case CWindowRule::RULE_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(trim(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_sWindowData.activeBorderColor = CWindowOverridableVar(CGradientValueData(CColor(configStringToInt(colorsAndAngles[0]))), priority);
|
||||
m_sWindowData.inactiveBorderColor = CWindowOverridableVar(CGradientValueData(CColor(configStringToInt(colorsAndAngles[1]))), priority);
|
||||
m_sWindowData.activeBorderColor = CWindowOverridableVar(CGradientValueData(CHyprColor(configStringToInt(colorsAndAngles[0]).value_or(0))), priority);
|
||||
m_sWindowData.inactiveBorderColor = CWindowOverridableVar(CGradientValueData(CHyprColor(configStringToInt(colorsAndAngles[1]).value_or(0))), 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);
|
||||
@@ -674,37 +696,29 @@ void CWindow::applyDynamicRule(const SWindowRule& r) {
|
||||
} else if (token.contains("deg"))
|
||||
inactiveBorderGradient.m_fAngle = std::stoi(token.substr(0, token.size() - 3)) * (PI / 180.0);
|
||||
else if (active)
|
||||
activeBorderGradient.m_vColors.push_back(configStringToInt(token));
|
||||
activeBorderGradient.m_vColors.push_back(configStringToInt(token).value_or(0));
|
||||
else
|
||||
inactiveBorderGradient.m_vColors.push_back(configStringToInt(token));
|
||||
inactiveBorderGradient.m_vColors.push_back(configStringToInt(token).value_or(0));
|
||||
}
|
||||
|
||||
activeBorderGradient.updateColorsOk();
|
||||
|
||||
// Includes sanity checks for the number of colors in each gradient
|
||||
if (activeBorderGradient.m_vColors.size() > 10 || inactiveBorderGradient.m_vColors.size() > 10)
|
||||
Debug::log(WARN, "Bordercolor rule \"{}\" has more than 10 colors in one gradient, ignoring", r.szRule);
|
||||
Debug::log(WARN, "Bordercolor rule \"{}\" has more than 10 colors in one gradient, ignoring", r->szRule);
|
||||
else if (activeBorderGradient.m_vColors.empty())
|
||||
Debug::log(WARN, "Bordercolor rule \"{}\" has no colors, ignoring", r.szRule);
|
||||
Debug::log(WARN, "Bordercolor rule \"{}\" has no colors, ignoring", r->szRule);
|
||||
else if (inactiveBorderGradient.m_vColors.empty())
|
||||
m_sWindowData.activeBorderColor = CWindowOverridableVar(activeBorderGradient, priority);
|
||||
else {
|
||||
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 (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 {
|
||||
*(search->second(m_pSelf.lock())) = CWindowOverridableVar((bool)configStringToInt(VARS[1]), priority);
|
||||
} catch (...) {}
|
||||
} catch (std::exception& e) { Debug::log(ERR, "BorderColor rule \"{}\" failed with: {}", r->szRule, e.what()); }
|
||||
break;
|
||||
}
|
||||
} 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);
|
||||
case CWindowRule::RULE_IDLEINHIBIT: {
|
||||
auto IDLERULE = r->szRule.substr(r->szRule.find_first_of(' ') + 1);
|
||||
|
||||
if (IDLERULE == "none")
|
||||
m_eIdleInhibitMode = IDLEINHIBIT_NONE;
|
||||
@@ -716,38 +730,65 @@ void CWindow::applyDynamicRule(const SWindowRule& r) {
|
||||
m_eIdleInhibitMode = IDLEINHIBIT_FULLSCREEN;
|
||||
else
|
||||
Debug::log(ERR, "Rule idleinhibit: unknown mode {}", IDLERULE);
|
||||
} else if (r.szRule.starts_with("maxsize")) {
|
||||
break;
|
||||
}
|
||||
case CWindowRule::RULE_MAXSIZE: {
|
||||
try {
|
||||
if (!m_bIsFloating)
|
||||
return;
|
||||
const auto VEC = configStringToVector2D(r.szRule.substr(8));
|
||||
const auto VEC = configStringToVector2D(r->szRule.substr(8));
|
||||
if (VEC.x < 1 || VEC.y < 1) {
|
||||
Debug::log(ERR, "Invalid size for maxsize");
|
||||
return;
|
||||
}
|
||||
|
||||
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")) {
|
||||
clampWindowSize(std::nullopt, m_sWindowData.maxSize.value());
|
||||
|
||||
} catch (std::exception& e) { Debug::log(ERR, "maxsize rule \"{}\" failed with: {}", r->szRule, e.what()); }
|
||||
break;
|
||||
}
|
||||
case CWindowRule::RULE_MINSIZE: {
|
||||
try {
|
||||
if (!m_bIsFloating)
|
||||
return;
|
||||
const auto VEC = configStringToVector2D(r.szRule.substr(8));
|
||||
const auto VEC = configStringToVector2D(r->szRule.substr(8));
|
||||
if (VEC.x < 1 || VEC.y < 1) {
|
||||
Debug::log(ERR, "Invalid size for minsize");
|
||||
return;
|
||||
}
|
||||
|
||||
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());
|
||||
clampWindowSize(m_sWindowData.minSize.value(), std::nullopt);
|
||||
|
||||
if (m_sGroupData.pNextWindow.expired())
|
||||
setHidden(false);
|
||||
} catch (std::exception& e) { Debug::log(ERR, "minsize rule \"{}\" failed with: {}", r.szRule, e.what()); }
|
||||
} catch (std::exception& e) { Debug::log(ERR, "minsize rule \"{}\" failed with: {}", r->szRule, e.what()); }
|
||||
break;
|
||||
}
|
||||
case CWindowRule::RULE_RENDERUNFOCUSED: {
|
||||
m_sWindowData.renderUnfocused = CWindowOverridableVar(true, priority);
|
||||
g_pHyprRenderer->addWindowToRenderUnfocused(m_pSelf.lock());
|
||||
break;
|
||||
}
|
||||
case CWindowRule::RULE_PROP: {
|
||||
const CVarList VARS(r->szRule, 0, ' ');
|
||||
if (auto search = g_pConfigManager->miWindowProperties.find(VARS[1]); search != g_pConfigManager->miWindowProperties.end()) {
|
||||
try {
|
||||
*(search->second(m_pSelf.lock())) = CWindowOverridableVar(std::stoi(VARS[2]), priority);
|
||||
} catch (std::exception& e) { Debug::log(ERR, "Rule \"{}\" failed with: {}", r->szRule, e.what()); }
|
||||
} else if (auto search = g_pConfigManager->mfWindowProperties.find(VARS[1]); search != g_pConfigManager->mfWindowProperties.end()) {
|
||||
try {
|
||||
*(search->second(m_pSelf.lock())) = CWindowOverridableVar(std::stof(VARS[2]), priority);
|
||||
} catch (std::exception& e) { Debug::log(ERR, "Rule \"{}\" failed with: {}", r->szRule, e.what()); }
|
||||
} else if (auto search = g_pConfigManager->mbWindowProperties.find(VARS[1]); search != g_pConfigManager->mbWindowProperties.end()) {
|
||||
try {
|
||||
*(search->second(m_pSelf.lock())) = CWindowOverridableVar(VARS[2].empty() ? true : (bool)std::stoi(VARS[2]), priority);
|
||||
} catch (std::exception& e) { Debug::log(ERR, "Rule \"{}\" failed with: {}", r->szRule, e.what()); }
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -765,18 +806,20 @@ void CWindow::updateDynamicRules() {
|
||||
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 (const auto& r : m_vMatchedRules) {
|
||||
applyDynamicRule(r);
|
||||
}
|
||||
|
||||
EMIT_HOOK_EVENT("windowUpdateRules", m_pSelf.lock());
|
||||
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m_iMonitorID);
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(monitorID());
|
||||
}
|
||||
|
||||
// check if the point is "hidden" under a rounded corner of the window
|
||||
@@ -841,9 +884,11 @@ void CWindow::createGroup() {
|
||||
|
||||
addWindowDeco(std::make_unique<CHyprGroupBarDecoration>(m_pSelf.lock()));
|
||||
|
||||
g_pCompositor->updateWorkspaceWindows(workspaceID());
|
||||
g_pCompositor->updateWorkspaceWindowData(workspaceID());
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m_iMonitorID);
|
||||
if (m_pWorkspace) {
|
||||
m_pWorkspace->updateWindows();
|
||||
m_pWorkspace->updateWindowData();
|
||||
}
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(monitorID());
|
||||
g_pCompositor->updateAllWindowsAnimatedDecorationValues();
|
||||
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"togglegroup", std::format("1,{:x}", (uintptr_t)this)});
|
||||
@@ -859,9 +904,11 @@ void CWindow::destroyGroup() {
|
||||
m_sGroupData.pNextWindow.reset();
|
||||
m_sGroupData.head = false;
|
||||
updateWindowDecos();
|
||||
g_pCompositor->updateWorkspaceWindows(workspaceID());
|
||||
g_pCompositor->updateWorkspaceWindowData(workspaceID());
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m_iMonitorID);
|
||||
if (m_pWorkspace) {
|
||||
m_pWorkspace->updateWindows();
|
||||
m_pWorkspace->updateWindowData();
|
||||
}
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(monitorID());
|
||||
g_pCompositor->updateAllWindowsAnimatedDecorationValues();
|
||||
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"togglegroup", std::format("0,{:x}", (uintptr_t)this)});
|
||||
@@ -881,7 +928,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;
|
||||
@@ -889,15 +936,17 @@ 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->updateWorkspaceWindowData(workspaceID());
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m_iMonitorID);
|
||||
if (m_pWorkspace) {
|
||||
m_pWorkspace->updateWindows();
|
||||
m_pWorkspace->updateWindowData();
|
||||
}
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(monitorID());
|
||||
g_pCompositor->updateAllWindowsAnimatedDecorationValues();
|
||||
|
||||
if (!addresses.empty())
|
||||
@@ -937,12 +986,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) {
|
||||
@@ -973,7 +1026,7 @@ void CWindow::setGroupCurrent(PHLWINDOW pWindow) {
|
||||
const auto PCURRENT = getGroupCurrent();
|
||||
const bool FULLSCREEN = PCURRENT->isFullscreen();
|
||||
const auto WORKSPACE = PCURRENT->m_pWorkspace;
|
||||
const auto MODE = PCURRENT->m_sFullscreenState.client;
|
||||
const auto MODE = PCURRENT->m_sFullscreenState.internal;
|
||||
|
||||
const auto PWINDOWSIZE = PCURRENT->m_vRealSize.goal();
|
||||
const auto PWINDOWPOS = PCURRENT->m_vRealPosition.goal();
|
||||
@@ -1069,7 +1122,7 @@ void CWindow::updateGroupOutputs() {
|
||||
const auto WS = m_pWorkspace;
|
||||
|
||||
while (curr.get() != this) {
|
||||
curr->m_iMonitorID = m_iMonitorID;
|
||||
curr->m_pMonitor = m_pMonitor;
|
||||
curr->moveToWorkspace(WS);
|
||||
|
||||
curr->m_vRealPosition = m_vRealPosition.goal();
|
||||
@@ -1150,6 +1203,16 @@ int CWindow::getRealBorderSize() {
|
||||
return m_sWindowData.borderSize.valueOr(*PBORDERSIZE);
|
||||
}
|
||||
|
||||
float CWindow::getScrollMouse() {
|
||||
static auto PINPUTSCROLLFACTOR = CConfigValue<Hyprlang::FLOAT>("input:scroll_factor");
|
||||
return m_sWindowData.scrollMouse.valueOr(*PINPUTSCROLLFACTOR);
|
||||
}
|
||||
|
||||
float CWindow::getScrollTouchpad() {
|
||||
static auto PTOUCHPADSCROLLFACTOR = CConfigValue<Hyprlang::FLOAT>("input:touchpad:scroll_factor");
|
||||
return m_sWindowData.scrollTouchpad.valueOr(*PTOUCHPADSCROLLFACTOR);
|
||||
}
|
||||
|
||||
bool CWindow::canBeTorn() {
|
||||
static auto PTEARING = CConfigValue<Hyprlang::INT>("general:allow_tearing");
|
||||
return m_sWindowData.tearing.valueOr(m_bTearingHint) && *PTEARING;
|
||||
@@ -1166,7 +1229,7 @@ void CWindow::setSuspended(bool suspend) {
|
||||
m_bSuspended = suspend;
|
||||
}
|
||||
|
||||
bool CWindow::visibleOnMonitor(CMonitor* pMonitor) {
|
||||
bool CWindow::visibleOnMonitor(PHLMONITOR pMonitor) {
|
||||
CBox wbox = {m_vRealPosition.value(), m_vRealSize.value()};
|
||||
|
||||
return !wbox.intersection({pMonitor->vecPosition, pMonitor->vecSize}).empty();
|
||||
@@ -1191,7 +1254,7 @@ void CWindow::onWorkspaceAnimUpdate() {
|
||||
if (!PWORKSPACE)
|
||||
return;
|
||||
|
||||
const auto PWSMON = g_pCompositor->getMonitorFromID(PWORKSPACE->m_iMonitorID);
|
||||
const auto PWSMON = m_pMonitor.lock();
|
||||
if (!PWSMON)
|
||||
return;
|
||||
|
||||
@@ -1235,6 +1298,16 @@ int CWindow::surfacesCount() {
|
||||
return no;
|
||||
}
|
||||
|
||||
void CWindow::clampWindowSize(const std::optional<Vector2D> minSize, const std::optional<Vector2D> maxSize) {
|
||||
const Vector2D REALSIZE = m_vRealSize.goal();
|
||||
const Vector2D NEWSIZE = REALSIZE.clamp(minSize.value_or(Vector2D{MIN_WINDOW_SIZE, MIN_WINDOW_SIZE}), maxSize.value_or(Vector2D{INFINITY, INFINITY}));
|
||||
const Vector2D DELTA = REALSIZE - NEWSIZE;
|
||||
|
||||
m_vRealPosition = m_vRealPosition.goal() + DELTA / 2.0;
|
||||
m_vRealSize = NEWSIZE;
|
||||
g_pXWaylandManager->setWindowSize(m_pSelf.lock(), NEWSIZE);
|
||||
}
|
||||
|
||||
bool CWindow::isFullscreen() {
|
||||
return m_sFullscreenState.internal != FSMODE_NONE;
|
||||
}
|
||||
@@ -1243,10 +1316,14 @@ bool CWindow::isEffectiveInternalFSMode(const eFullscreenMode MODE) {
|
||||
return (eFullscreenMode)std::bit_floor((uint8_t)m_sFullscreenState.internal) == MODE;
|
||||
}
|
||||
|
||||
int CWindow::workspaceID() {
|
||||
WORKSPACEID CWindow::workspaceID() {
|
||||
return m_pWorkspace ? m_pWorkspace->m_iID : m_iLastWorkspace;
|
||||
}
|
||||
|
||||
MONITORID CWindow::monitorID() {
|
||||
return m_pMonitor ? m_pMonitor->ID : MONITOR_INVALID;
|
||||
}
|
||||
|
||||
bool CWindow::onSpecialWorkspace() {
|
||||
return m_pWorkspace ? m_pWorkspace->m_bIsSpecialWorkspace : g_pCompositor->isWorkspaceSpecial(m_iLastWorkspace);
|
||||
}
|
||||
@@ -1282,7 +1359,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;
|
||||
|
||||
@@ -1307,6 +1384,11 @@ void CWindow::activate(bool force) {
|
||||
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);
|
||||
|
||||
@@ -1428,7 +1510,7 @@ void CWindow::onX11Configure(CBox box) {
|
||||
m_pXWaylandSurface->configure(box);
|
||||
m_vPendingReportedSize = box.size();
|
||||
m_vReportedSize = box.size();
|
||||
if (const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID); PMONITOR)
|
||||
if (const auto PMONITOR = m_pMonitor.lock(); PMONITOR)
|
||||
m_fX11SurfaceScaledBy = PMONITOR->scale;
|
||||
return;
|
||||
}
|
||||
@@ -1454,7 +1536,7 @@ void CWindow::onX11Configure(CBox box) {
|
||||
|
||||
static auto PXWLFORCESCALEZERO = CConfigValue<Hyprlang::INT>("xwayland:force_zero_scaling");
|
||||
if (*PXWLFORCESCALEZERO) {
|
||||
if (const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID); PMONITOR) {
|
||||
if (const auto PMONITOR = m_pMonitor.lock(); PMONITOR) {
|
||||
m_vRealSize.setValueAndWarp(m_vRealSize.goal() / PMONITOR->scale);
|
||||
m_fX11SurfaceScaledBy = PMONITOR->scale;
|
||||
}
|
||||
@@ -1470,7 +1552,7 @@ void CWindow::onX11Configure(CBox box) {
|
||||
|
||||
updateWindowDecos();
|
||||
|
||||
if (!g_pCompositor->isWorkspaceVisible(m_pWorkspace))
|
||||
if (!m_pWorkspace || !m_pWorkspace->isVisible())
|
||||
return; // further things are only for visible windows
|
||||
|
||||
m_pWorkspace = g_pCompositor->getMonitorFromVector(m_vRealPosition.value() + m_vRealSize.value() / 2.f)->activeWorkspace;
|
||||
@@ -1482,15 +1564,15 @@ void CWindow::onX11Configure(CBox box) {
|
||||
g_pHyprRenderer->damageWindow(m_pSelf.lock());
|
||||
}
|
||||
|
||||
void CWindow::warpCursor() {
|
||||
void CWindow::warpCursor(bool force) {
|
||||
static auto PERSISTENTWARPS = CConfigValue<Hyprlang::INT>("cursor:persistent_warps");
|
||||
const auto coords = m_vRelativeCursorCoordsOnLastWarp;
|
||||
m_vRelativeCursorCoordsOnLastWarp.x = -1; // reset m_vRelativeCursorCoordsOnLastWarp
|
||||
|
||||
if (*PERSISTENTWARPS && coords.x > 0 && coords.y > 0 && coords < m_vSize) // don't warp cursor outside the window
|
||||
g_pCompositor->warpCursorTo(m_vPosition + coords);
|
||||
g_pCompositor->warpCursorTo(m_vPosition + coords, force);
|
||||
else
|
||||
g_pCompositor->warpCursorTo(middle());
|
||||
g_pCompositor->warpCursorTo(middle(), force);
|
||||
}
|
||||
|
||||
PHLWINDOW CWindow::getSwallower() {
|
||||
@@ -1498,7 +1580,7 @@ PHLWINDOW CWindow::getSwallower() {
|
||||
static auto PSWALLOWEXREGEX = CConfigValue<std::string>("misc:swallow_exception_regex");
|
||||
static auto PSWALLOW = CConfigValue<Hyprlang::INT>("misc:enable_swallow");
|
||||
|
||||
if (!*PSWALLOW || (*PSWALLOWREGEX).empty())
|
||||
if (!*PSWALLOW || std::string{*PSWALLOWREGEX} == STRVAL_EMPTY || (*PSWALLOWREGEX).empty())
|
||||
return nullptr;
|
||||
|
||||
// check parent
|
||||
@@ -1511,7 +1593,7 @@ PHLWINDOW CWindow::getSwallower() {
|
||||
if (!currentPid)
|
||||
break;
|
||||
|
||||
for (auto& w : g_pCompositor->m_vWindows) {
|
||||
for (auto const& w : g_pCompositor->m_vWindows) {
|
||||
if (!w->m_bIsMapped || w->isHidden())
|
||||
continue;
|
||||
|
||||
@@ -1521,13 +1603,13 @@ PHLWINDOW CWindow::getSwallower() {
|
||||
}
|
||||
|
||||
if (!(*PSWALLOWREGEX).empty())
|
||||
std::erase_if(candidates, [&](const auto& other) { return !std::regex_match(other->m_szClass, std::regex(*PSWALLOWREGEX)); });
|
||||
std::erase_if(candidates, [&](const auto& other) { return !RE2::FullMatch(other->m_szClass, *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)); });
|
||||
std::erase_if(candidates, [&](const auto& other) { return RE2::FullMatch(other->m_szTitle, *PSWALLOWEXREGEX); });
|
||||
|
||||
if (candidates.size() <= 0)
|
||||
return nullptr;
|
||||
@@ -1536,7 +1618,7 @@ PHLWINDOW CWindow::getSwallower() {
|
||||
return candidates.at(0);
|
||||
|
||||
// walk up the focus history and find the last focused
|
||||
for (auto& w : g_pCompositor->m_vWindowFocusHistory) {
|
||||
for (auto const& w : g_pCompositor->m_vWindowFocusHistory) {
|
||||
if (!w)
|
||||
continue;
|
||||
|
||||
@@ -1555,4 +1637,41 @@ void CWindow::unsetWindowData(eOverridePriority priority) {
|
||||
for (auto const& element : g_pConfigManager->miWindowProperties) {
|
||||
element.second(m_pSelf.lock())->unset(priority);
|
||||
}
|
||||
for (auto const& element : g_pConfigManager->mfWindowProperties) {
|
||||
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);
|
||||
}
|
||||
|
||||
Vector2D CWindow::requestedMinSize() {
|
||||
if ((m_bIsX11 && !m_pXWaylandSurface->sizeHints) || (!m_bIsX11 && !m_pXDGSurface->toplevel))
|
||||
return Vector2D(1, 1);
|
||||
|
||||
Vector2D minSize = m_bIsX11 ? Vector2D(m_pXWaylandSurface->sizeHints->min_width, m_pXWaylandSurface->sizeHints->min_height) : m_pXDGSurface->toplevel->layoutMinSize();
|
||||
|
||||
minSize = minSize.clamp({1, 1});
|
||||
|
||||
return minSize;
|
||||
}
|
||||
|
||||
Vector2D CWindow::requestedMaxSize() {
|
||||
constexpr int NO_MAX_SIZE_LIMIT = 99999;
|
||||
if (((m_bIsX11 && !m_pXWaylandSurface->sizeHints) || (!m_bIsX11 && !m_pXDGSurface->toplevel) || m_sWindowData.noMaxSize.valueOrDefault()))
|
||||
return Vector2D(NO_MAX_SIZE_LIMIT, NO_MAX_SIZE_LIMIT);
|
||||
|
||||
Vector2D maxSize = m_bIsX11 ? Vector2D(m_pXWaylandSurface->sizeHints->max_width, m_pXWaylandSurface->sizeHints->max_height) : m_pXDGSurface->toplevel->layoutMaxSize();
|
||||
|
||||
if (maxSize.x < 5)
|
||||
maxSize.x = NO_MAX_SIZE_LIMIT;
|
||||
if (maxSize.y < 5)
|
||||
maxSize.y = NO_MAX_SIZE_LIMIT;
|
||||
|
||||
return maxSize;
|
||||
}
|
||||
|
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <deque>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include "../config/ConfigDataValues.hpp"
|
||||
@@ -17,18 +17,19 @@
|
||||
#include "Subsurface.hpp"
|
||||
#include "WLSurface.hpp"
|
||||
#include "Workspace.hpp"
|
||||
#include "WindowRule.hpp"
|
||||
|
||||
class CXDGSurfaceResource;
|
||||
class CXWaylandSurface;
|
||||
|
||||
enum eIdleInhibitMode {
|
||||
enum eIdleInhibitMode : uint8_t {
|
||||
IDLEINHIBIT_NONE = 0,
|
||||
IDLEINHIBIT_ALWAYS,
|
||||
IDLEINHIBIT_FULLSCREEN,
|
||||
IDLEINHIBIT_FOCUS
|
||||
};
|
||||
|
||||
enum eGroupRules {
|
||||
enum eGroupRules : uint8_t {
|
||||
// effective only during first map, except for _ALWAYS variant
|
||||
GROUP_NONE = 0,
|
||||
GROUP_SET = 1 << 0, // Open as new group or add to focused group
|
||||
@@ -40,7 +41,7 @@ enum eGroupRules {
|
||||
GROUP_OVERRIDE = 1 << 6, // Override other rules
|
||||
};
|
||||
|
||||
enum eGetWindowProperties {
|
||||
enum eGetWindowProperties : uint8_t {
|
||||
WINDOW_ONLY = 0,
|
||||
RESERVED_EXTENTS = 1 << 0,
|
||||
INPUT_EXTENTS = 1 << 1,
|
||||
@@ -50,7 +51,7 @@ enum eGetWindowProperties {
|
||||
USE_PROP_TILED = 1 << 5,
|
||||
};
|
||||
|
||||
enum eSuppressEvents {
|
||||
enum eSuppressEvents : uint8_t {
|
||||
SUPPRESS_NONE = 0,
|
||||
SUPPRESS_FULLSCREEN = 1 << 0,
|
||||
SUPPRESS_MAXIMIZE = 1 << 1,
|
||||
@@ -64,7 +65,7 @@ struct SAlphaValue {
|
||||
float m_fAlpha;
|
||||
bool m_bOverride;
|
||||
|
||||
float applyAlpha(float alpha) {
|
||||
float applyAlpha(float alpha) const {
|
||||
if (m_bOverride)
|
||||
return m_fAlpha;
|
||||
else
|
||||
@@ -72,8 +73,8 @@ struct SAlphaValue {
|
||||
};
|
||||
};
|
||||
|
||||
enum eOverridePriority {
|
||||
PRIORITY_LAYOUT,
|
||||
enum eOverridePriority : uint8_t {
|
||||
PRIORITY_LAYOUT = 0,
|
||||
PRIORITY_WORKSPACE_RULE,
|
||||
PRIORITY_WINDOW_RULE,
|
||||
PRIORITY_SET_PROP,
|
||||
@@ -85,9 +86,7 @@ class CWindowOverridableVar {
|
||||
CWindowOverridableVar(T const& value, eOverridePriority priority) {
|
||||
values[priority] = value;
|
||||
}
|
||||
CWindowOverridableVar(T const& value) {
|
||||
defaultValue = value;
|
||||
}
|
||||
CWindowOverridableVar(T const& value) : defaultValue{value} {}
|
||||
|
||||
CWindowOverridableVar() = default;
|
||||
~CWindowOverridableVar() = default;
|
||||
@@ -144,6 +143,13 @@ class CWindowOverridableVar {
|
||||
unset(priority);
|
||||
}
|
||||
|
||||
operator std::optional<T>() {
|
||||
if (hasValue())
|
||||
return value();
|
||||
else
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
private:
|
||||
std::map<eOverridePriority, T> values;
|
||||
T defaultValue; // used for toggling, so required for bool
|
||||
@@ -174,10 +180,14 @@ struct SWindowData {
|
||||
CWindowOverridableVar<bool> syncFullscreen = true;
|
||||
CWindowOverridableVar<bool> tearing = false;
|
||||
CWindowOverridableVar<bool> xray = false;
|
||||
CWindowOverridableVar<bool> renderUnfocused = false;
|
||||
|
||||
CWindowOverridableVar<int> rounding;
|
||||
CWindowOverridableVar<int> borderSize;
|
||||
|
||||
CWindowOverridableVar<float> scrollMouse;
|
||||
CWindowOverridableVar<float> scrollTouchpad;
|
||||
|
||||
CWindowOverridableVar<std::string> animationStyle;
|
||||
CWindowOverridableVar<Vector2D> maxSize;
|
||||
CWindowOverridableVar<Vector2D> minSize;
|
||||
@@ -186,31 +196,12 @@ struct SWindowData {
|
||||
CWindowOverridableVar<CGradientValueData> inactiveBorderColor;
|
||||
};
|
||||
|
||||
struct SWindowRule {
|
||||
std::string szRule;
|
||||
std::string szValue;
|
||||
|
||||
bool v2 = false;
|
||||
std::string szTitle;
|
||||
std::string szClass;
|
||||
std::string szInitialTitle;
|
||||
std::string szInitialClass;
|
||||
std::string szTag;
|
||||
int bX11 = -1; // -1 means "ANY"
|
||||
int bFloating = -1;
|
||||
int bFullscreen = -1;
|
||||
int bPinned = -1;
|
||||
int bFocus = -1;
|
||||
std::string szOnWorkspace = ""; // empty means any
|
||||
std::string szWorkspace = ""; // empty means any
|
||||
};
|
||||
|
||||
struct SInitialWorkspaceToken {
|
||||
PHLWINDOWREF primaryOwner;
|
||||
std::string workspace;
|
||||
};
|
||||
|
||||
struct sFullscreenState {
|
||||
struct SFullscreenState {
|
||||
eFullscreenMode internal = FSMODE_NONE;
|
||||
eFullscreenMode client = FSMODE_NONE;
|
||||
};
|
||||
@@ -269,13 +260,13 @@ class CWindow {
|
||||
bool m_bIsFloating = false;
|
||||
bool m_bDraggingTiled = false; // for dragging around tiled windows
|
||||
bool m_bWasMaximized = false;
|
||||
sFullscreenState m_sFullscreenState = {.internal = FSMODE_NONE, .client = FSMODE_NONE};
|
||||
uint64_t m_iMonitorID = -1;
|
||||
SFullscreenState m_sFullscreenState = {.internal = FSMODE_NONE, .client = FSMODE_NONE};
|
||||
std::string m_szTitle = "";
|
||||
std::string m_szClass = "";
|
||||
std::string m_szInitialTitle = "";
|
||||
std::string m_szInitialClass = "";
|
||||
PHLWORKSPACE m_pWorkspace;
|
||||
PHLMONITORREF m_pMonitor;
|
||||
|
||||
bool m_bIsMapped = false;
|
||||
|
||||
@@ -287,8 +278,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;
|
||||
@@ -325,6 +314,9 @@ class CWindow {
|
||||
// For pinned (sticky) windows
|
||||
bool m_bPinned = false;
|
||||
|
||||
// For preserving pinned state when fullscreening a pinned window
|
||||
bool m_bPinFullscreened = false;
|
||||
|
||||
// urgency hint
|
||||
bool m_bIsUrgent = false;
|
||||
|
||||
@@ -333,7 +325,7 @@ class CWindow {
|
||||
|
||||
// Window decorations
|
||||
// TODO: make this a SP.
|
||||
std::deque<std::unique_ptr<IHyprWindowDecoration>> m_dWindowDecorations;
|
||||
std::vector<std::unique_ptr<IHyprWindowDecoration>> m_dWindowDecorations;
|
||||
std::vector<IHyprWindowDecoration*> m_vDecosToRemove;
|
||||
|
||||
// Special render data, rules, etc
|
||||
@@ -346,20 +338,25 @@ class CWindow {
|
||||
CAnimatedVariable<float> m_fActiveInactiveAlpha;
|
||||
|
||||
// animated shadow color
|
||||
CAnimatedVariable<CColor> m_cRealShadowColor;
|
||||
CAnimatedVariable<CHyprColor> m_cRealShadowColor;
|
||||
|
||||
// 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;
|
||||
bool m_bGroupSwallowed = false;
|
||||
|
||||
// focus stuff
|
||||
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;
|
||||
@@ -379,13 +376,13 @@ class CWindow {
|
||||
bool m_bTearingHint = false;
|
||||
|
||||
// stores the currently matched window rules
|
||||
std::vector<SWindowRule> m_vMatchedRules;
|
||||
std::vector<SP<CWindowRule>> m_vMatchedRules;
|
||||
|
||||
// window tags
|
||||
CTagKeeper m_tags;
|
||||
|
||||
// For the list lookup
|
||||
bool operator==(const CWindow& rhs) {
|
||||
bool operator==(const CWindow& rhs) const {
|
||||
return m_pXDGSurface == rhs.m_pXDGSurface && m_pXWaylandSurface == rhs.m_pXWaylandSurface && m_vPosition == rhs.m_vPosition && m_vSize == rhs.m_vSize &&
|
||||
m_bFadingOut == rhs.m_bFadingOut;
|
||||
}
|
||||
@@ -394,7 +391,6 @@ class CWindow {
|
||||
CBox getFullWindowBoundingBox();
|
||||
SBoxExtents getFullWindowExtents();
|
||||
CBox getWindowBoxUnified(uint64_t props);
|
||||
CBox getWindowMainSurfaceBox();
|
||||
CBox getWindowIdealBoundingBoxIgnoreReserved();
|
||||
void addWindowDeco(std::unique_ptr<IHyprWindowDecoration> deco);
|
||||
void updateWindowDecos();
|
||||
@@ -407,12 +403,12 @@ class CWindow {
|
||||
void updateToplevel();
|
||||
void updateSurfaceScaleTransformDetails(bool force = false);
|
||||
void moveToWorkspace(PHLWORKSPACE);
|
||||
PHLWINDOW X11TransientFor();
|
||||
PHLWINDOW x11TransientFor();
|
||||
void onUnmap();
|
||||
void onMap();
|
||||
void setHidden(bool hidden);
|
||||
bool isHidden();
|
||||
void applyDynamicRule(const SWindowRule& r);
|
||||
void applyDynamicRule(const SP<CWindowRule>& r);
|
||||
void updateDynamicRules();
|
||||
SBoxExtents getFullWindowReservedArea();
|
||||
Vector2D middle();
|
||||
@@ -420,24 +416,24 @@ class CWindow {
|
||||
float rounding();
|
||||
bool canBeTorn();
|
||||
void setSuspended(bool suspend);
|
||||
bool visibleOnMonitor(CMonitor* pMonitor);
|
||||
int workspaceID();
|
||||
bool visibleOnMonitor(PHLMONITOR pMonitor);
|
||||
WORKSPACEID workspaceID();
|
||||
MONITORID monitorID();
|
||||
bool onSpecialWorkspace();
|
||||
void activate(bool force = false);
|
||||
int surfacesCount();
|
||||
|
||||
void clampWindowSize(const std::optional<Vector2D> minSize, const std::optional<Vector2D> maxSize);
|
||||
bool isFullscreen();
|
||||
bool isEffectiveInternalFSMode(const eFullscreenMode);
|
||||
|
||||
int getRealBorderSize();
|
||||
float getScrollMouse();
|
||||
float getScrollTouchpad();
|
||||
void updateWindowData();
|
||||
void updateWindowData(const struct SWorkspaceRule&);
|
||||
|
||||
void onBorderAngleAnimEnd(void* ptr);
|
||||
bool isInCurvedCorner(double x, double y);
|
||||
bool hasPopupAt(const Vector2D& pos);
|
||||
int popupsCount();
|
||||
|
||||
void applyGroupRules();
|
||||
void createGroup();
|
||||
void destroyGroup();
|
||||
@@ -460,9 +456,17 @@ class CWindow {
|
||||
void onResourceChangeX11();
|
||||
std::string fetchTitle();
|
||||
std::string fetchClass();
|
||||
void warpCursor();
|
||||
void warpCursor(bool force = false);
|
||||
PHLWINDOW getSwallower();
|
||||
void unsetWindowData(eOverridePriority priority);
|
||||
bool isX11OverrideRedirect();
|
||||
bool isModal();
|
||||
Vector2D requestedMinSize();
|
||||
Vector2D requestedMaxSize();
|
||||
|
||||
CBox getWindowMainSurfaceBox() const {
|
||||
return {m_vRealPosition.value().x, m_vRealPosition.value().y, m_vRealSize.value().x, m_vRealSize.value().y};
|
||||
}
|
||||
|
||||
// listeners
|
||||
void onAck(uint32_t serial);
|
||||
@@ -492,7 +496,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) {
|
||||
@@ -549,7 +553,7 @@ struct std::formatter<PHLWINDOW, CharT> : std::formatter<CharT> {
|
||||
if (formatWorkspace)
|
||||
std::format_to(out, ", workspace: {}", w->m_pWorkspace ? w->workspaceID() : WORKSPACE_INVALID);
|
||||
if (formatMonitor)
|
||||
std::format_to(out, ", monitor: {}", w->m_iMonitorID);
|
||||
std::format_to(out, ", monitor: {}", w->monitorID());
|
||||
if (formatClass)
|
||||
std::format_to(out, ", class: {}", w->m_szClass);
|
||||
return std::format_to(out, "]");
|
||||
|
100
src/desktop/WindowRule.cpp
Normal file
@@ -0,0 +1,100 @@
|
||||
#include "WindowRule.hpp"
|
||||
#include <unordered_set>
|
||||
#include <algorithm>
|
||||
#include "../config/ConfigManager.hpp"
|
||||
|
||||
static const auto RULES = std::unordered_set<std::string>{
|
||||
"float", "fullscreen", "maximize", "noinitialfocus", "pin", "stayfocused", "tile", "renderunfocused",
|
||||
};
|
||||
static const auto RULES_PREFIX = std::unordered_set<std::string>{
|
||||
"animation", "bordercolor", "bordersize", "center", "fullscreenstate", "group", "idleinhibit", "maxsize", "minsize", "monitor", "move", "opacity",
|
||||
"plugin:", "prop", "pseudo", "rounding", "scrollmouse", "scrolltouchpad", "size", "suppressevent", "tag", "workspace", "xray",
|
||||
};
|
||||
|
||||
CWindowRule::CWindowRule(const std::string& rule, const std::string& value, bool isV2, bool isExecRule) : szValue(value), szRule(rule), v2(isV2), execRule(isExecRule) {
|
||||
const auto VALS = CVarList(rule, 2, ' ');
|
||||
const bool VALID = RULES.contains(rule) || std::any_of(RULES_PREFIX.begin(), RULES_PREFIX.end(), [&rule](auto prefix) { return rule.starts_with(prefix); }) ||
|
||||
(g_pConfigManager->mbWindowProperties.find(VALS[0]) != g_pConfigManager->mbWindowProperties.end()) ||
|
||||
(g_pConfigManager->miWindowProperties.find(VALS[0]) != g_pConfigManager->miWindowProperties.end()) ||
|
||||
(g_pConfigManager->mfWindowProperties.find(VALS[0]) != g_pConfigManager->mfWindowProperties.end());
|
||||
|
||||
if (!VALID)
|
||||
return;
|
||||
|
||||
if (rule == "float")
|
||||
ruleType = RULE_FLOAT;
|
||||
else if (rule == "fullscreen")
|
||||
ruleType = RULE_FULLSCREEN;
|
||||
else if (rule == "maximize")
|
||||
ruleType = RULE_MAXIMIZE;
|
||||
else if (rule == "noinitialfocus")
|
||||
ruleType = RULE_NOINITIALFOCUS;
|
||||
else if (rule == "pin")
|
||||
ruleType = RULE_PIN;
|
||||
else if (rule == "stayfocused")
|
||||
ruleType = RULE_STAYFOCUSED;
|
||||
else if (rule == "tile")
|
||||
ruleType = RULE_TILE;
|
||||
else if (rule == "renderunfocused")
|
||||
ruleType = RULE_RENDERUNFOCUSED;
|
||||
else if (rule.starts_with("animation"))
|
||||
ruleType = RULE_ANIMATION;
|
||||
else if (rule.starts_with("bordercolor"))
|
||||
ruleType = RULE_BORDERCOLOR;
|
||||
else if (rule.starts_with("bordersize"))
|
||||
ruleType = RULE_BORDERSIZE;
|
||||
else if (rule.starts_with("center"))
|
||||
ruleType = RULE_CENTER;
|
||||
else if (rule.starts_with("fullscreenstate"))
|
||||
ruleType = RULE_FULLSCREENSTATE;
|
||||
else if (rule.starts_with("group"))
|
||||
ruleType = RULE_GROUP;
|
||||
else if (rule.starts_with("idleinhibit"))
|
||||
ruleType = RULE_IDLEINHIBIT;
|
||||
else if (rule.starts_with("maxsize"))
|
||||
ruleType = RULE_MAXSIZE;
|
||||
else if (rule.starts_with("minsize"))
|
||||
ruleType = RULE_MINSIZE;
|
||||
else if (rule.starts_with("monitor"))
|
||||
ruleType = RULE_MONITOR;
|
||||
else if (rule.starts_with("move"))
|
||||
ruleType = RULE_MOVE;
|
||||
else if (rule.starts_with("opacity"))
|
||||
ruleType = RULE_OPACITY;
|
||||
else if (rule.starts_with("plugin:"))
|
||||
ruleType = RULE_PLUGIN;
|
||||
else if (rule.starts_with("pseudo"))
|
||||
ruleType = RULE_PSEUDO;
|
||||
else if (rule.starts_with("rounding"))
|
||||
ruleType = RULE_ROUNDING;
|
||||
else if (rule.starts_with("scrollmouse"))
|
||||
ruleType = RULE_SCROLLMOUSE;
|
||||
else if (rule.starts_with("scrolltouchpad"))
|
||||
ruleType = RULE_SCROLLTOUCHPAD;
|
||||
else if (rule.starts_with("size"))
|
||||
ruleType = RULE_SIZE;
|
||||
else if (rule.starts_with("suppressevent"))
|
||||
ruleType = RULE_SUPPRESSEVENT;
|
||||
else if (rule.starts_with("tag"))
|
||||
ruleType = RULE_TAG;
|
||||
else if (rule.starts_with("workspace"))
|
||||
ruleType = RULE_WORKSPACE;
|
||||
else if (rule.starts_with("xray"))
|
||||
ruleType = RULE_XRAY;
|
||||
else if (rule.starts_with("prop"))
|
||||
ruleType = RULE_PROP;
|
||||
else {
|
||||
// check if this is a prop.
|
||||
const CVarList VARS(rule, 0, 's', true);
|
||||
if (g_pConfigManager->miWindowProperties.find(VARS[0]) != g_pConfigManager->miWindowProperties.end() ||
|
||||
g_pConfigManager->mbWindowProperties.find(VARS[0]) != g_pConfigManager->mbWindowProperties.end() ||
|
||||
g_pConfigManager->mfWindowProperties.find(VARS[0]) != g_pConfigManager->mfWindowProperties.end()) {
|
||||
*const_cast<std::string*>(&szRule) = "prop " + rule;
|
||||
ruleType = RULE_PROP;
|
||||
Debug::log(LOG, "CWindowRule: direct prop rule found, rewritten {} -> {}", rule, szRule);
|
||||
} else {
|
||||
Debug::log(ERR, "CWindowRule: didn't match a rule that was found valid?!");
|
||||
ruleType = RULE_INVALID;
|
||||
}
|
||||
}
|
||||
}
|
65
src/desktop/WindowRule.hpp
Normal file
@@ -0,0 +1,65 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <cstdint>
|
||||
|
||||
class CWindowRule {
|
||||
public:
|
||||
CWindowRule(const std::string& rule, const std::string& value, bool isV2 = false, bool isExecRule = false);
|
||||
|
||||
enum eRuleType : uint8_t {
|
||||
RULE_INVALID = 0,
|
||||
RULE_FLOAT,
|
||||
RULE_FULLSCREEN,
|
||||
RULE_MAXIMIZE,
|
||||
RULE_NOINITIALFOCUS,
|
||||
RULE_PIN,
|
||||
RULE_STAYFOCUSED,
|
||||
RULE_TILE,
|
||||
RULE_RENDERUNFOCUSED,
|
||||
RULE_ANIMATION,
|
||||
RULE_BORDERCOLOR,
|
||||
RULE_BORDERSIZE,
|
||||
RULE_CENTER,
|
||||
RULE_FULLSCREENSTATE,
|
||||
RULE_GROUP,
|
||||
RULE_IDLEINHIBIT,
|
||||
RULE_MAXSIZE,
|
||||
RULE_MINSIZE,
|
||||
RULE_MONITOR,
|
||||
RULE_MOVE,
|
||||
RULE_OPACITY,
|
||||
RULE_PLUGIN,
|
||||
RULE_PSEUDO,
|
||||
RULE_ROUNDING,
|
||||
RULE_SCROLLMOUSE,
|
||||
RULE_SCROLLTOUCHPAD,
|
||||
RULE_SIZE,
|
||||
RULE_SUPPRESSEVENT,
|
||||
RULE_TAG,
|
||||
RULE_WORKSPACE,
|
||||
RULE_XRAY,
|
||||
RULE_PROP,
|
||||
};
|
||||
|
||||
eRuleType ruleType = RULE_INVALID;
|
||||
|
||||
const std::string szValue;
|
||||
const std::string szRule;
|
||||
const bool v2 = false;
|
||||
const bool execRule = false;
|
||||
|
||||
std::string szTitle;
|
||||
std::string szClass;
|
||||
std::string szInitialTitle;
|
||||
std::string szInitialClass;
|
||||
std::string szTag;
|
||||
int bX11 = -1; // -1 means "ANY"
|
||||
int bFloating = -1;
|
||||
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
|
||||
};
|
@@ -5,27 +5,25 @@
|
||||
#include <hyprutils/string/String.hpp>
|
||||
using namespace Hyprutils::String;
|
||||
|
||||
PHLWORKSPACE CWorkspace::create(int id, int monitorID, std::string name, bool special, bool isEmtpy) {
|
||||
PHLWORKSPACE workspace = makeShared<CWorkspace>(id, monitorID, name, special, isEmtpy);
|
||||
PHLWORKSPACE CWorkspace::create(WORKSPACEID id, PHLMONITOR monitor, std::string name, bool special, bool isEmpty) {
|
||||
PHLWORKSPACE workspace = makeShared<CWorkspace>(id, monitor, name, special, isEmpty);
|
||||
workspace->init(workspace);
|
||||
return workspace;
|
||||
}
|
||||
|
||||
CWorkspace::CWorkspace(int id, int monitorID, std::string name, bool special, bool isEmtpy) {
|
||||
m_iMonitorID = monitorID;
|
||||
m_iID = id;
|
||||
m_szName = name;
|
||||
m_bIsSpecialWorkspace = special;
|
||||
m_bWasCreatedEmtpy = isEmtpy;
|
||||
CWorkspace::CWorkspace(WORKSPACEID id, PHLMONITOR monitor, std::string name, bool special, bool isEmpty) :
|
||||
m_iID(id), m_szName(name), m_pMonitor(monitor), m_bIsSpecialWorkspace(special), 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);
|
||||
|
||||
@@ -48,9 +46,9 @@ 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)});
|
||||
@@ -81,12 +79,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;
|
||||
|
||||
@@ -95,10 +100,10 @@ void CWorkspace::startAnim(bool in, bool left, bool instant) {
|
||||
});
|
||||
|
||||
if (ANIMSTYLE.starts_with("slidefade")) {
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
|
||||
const auto PMONITOR = m_pMonitor.lock();
|
||||
float movePerc = 100.f;
|
||||
|
||||
if (ANIMSTYLE.find("%") != std::string::npos) {
|
||||
if (ANIMSTYLE.find('%') != std::string::npos) {
|
||||
try {
|
||||
auto percstr = ANIMSTYLE.substr(ANIMSTYLE.find_last_of(' ') + 1);
|
||||
movePerc = std::stoi(percstr.substr(0, percstr.length() - 1));
|
||||
@@ -143,7 +148,7 @@ void CWorkspace::startAnim(bool in, bool left, bool instant) {
|
||||
}
|
||||
} else if (ANIMSTYLE == "slidevert") {
|
||||
// fallback is slide
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
|
||||
const auto PMONITOR = m_pMonitor.lock();
|
||||
const auto YDISTANCE = PMONITOR->vecSize.y + *PWORKSPACEGAP;
|
||||
|
||||
m_fAlpha.setValueAndWarp(1.f); // fix a bug, if switching from fade -> slide.
|
||||
@@ -156,7 +161,7 @@ void CWorkspace::startAnim(bool in, bool left, bool instant) {
|
||||
}
|
||||
} else {
|
||||
// fallback is slide
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
|
||||
const auto PMONITOR = m_pMonitor.lock();
|
||||
const auto XDISTANCE = PMONITOR->vecSize.x + *PWORKSPACEGAP;
|
||||
|
||||
m_fAlpha.setValueAndWarp(1.f); // fix a bug, if switching from fade -> slide.
|
||||
@@ -190,7 +195,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
|
||||
}
|
||||
|
||||
@@ -216,7 +221,7 @@ void CWorkspace::rememberPrevWorkspace(const PHLWORKSPACE& prev) {
|
||||
m_sPrevWorkspace.id = prev->m_iID;
|
||||
m_sPrevWorkspace.name = prev->m_szName;
|
||||
|
||||
if (prev->m_iMonitorID == m_iMonitorID) {
|
||||
if (prev->m_pMonitor == m_pMonitor) {
|
||||
m_sPrevWorkspacePerMonitor.id = prev->m_iID;
|
||||
m_sPrevWorkspacePerMonitor.name = prev->m_szName;
|
||||
}
|
||||
@@ -270,12 +275,12 @@ bool CWorkspace::matchesStaticSelector(const std::string& selector_) {
|
||||
// f - fullscreen state : f[-1], f[0], f[1], or f[2] for different fullscreen states
|
||||
// -1: no fullscreen, 0: fullscreen, 1: maximized, 2: fullscreen without sending fs state to window
|
||||
|
||||
const auto NEXTSPACE = selector.find_first_of(' ', i);
|
||||
std::string prop = selector.substr(i, NEXTSPACE == std::string::npos ? std::string::npos : NEXTSPACE - i);
|
||||
i = std::min(NEXTSPACE, std::string::npos - 1);
|
||||
const auto CLOSING_BRACKET = selector.find_first_of(']', i);
|
||||
std::string prop = selector.substr(i, CLOSING_BRACKET == std::string::npos ? std::string::npos : CLOSING_BRACKET + 1 - i);
|
||||
i = std::min(CLOSING_BRACKET, 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;
|
||||
@@ -288,7 +293,7 @@ bool CWorkspace::matchesStaticSelector(const std::string& selector_) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto DASHPOS = prop.find("-");
|
||||
const auto DASHPOS = prop.find('-');
|
||||
const auto LHS = prop.substr(0, DASHPOS), RHS = prop.substr(DASHPOS + 1);
|
||||
|
||||
if (!isNumber(LHS) || !isNumber(RHS)) {
|
||||
@@ -324,7 +329,7 @@ bool CWorkspace::matchesStaticSelector(const std::string& selector_) {
|
||||
|
||||
const auto SHOULDBESPECIAL = configStringToInt(prop);
|
||||
|
||||
if ((bool)SHOULDBESPECIAL != m_bIsSpecialWorkspace)
|
||||
if (SHOULDBESPECIAL && (bool)*SHOULDBESPECIAL != m_bIsSpecialWorkspace)
|
||||
return false;
|
||||
continue;
|
||||
}
|
||||
@@ -339,7 +344,7 @@ bool CWorkspace::matchesStaticSelector(const std::string& selector_) {
|
||||
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromString(prop);
|
||||
|
||||
if (!(PMONITOR ? PMONITOR->ID == m_iMonitorID : false))
|
||||
if (!(PMONITOR ? PMONITOR == m_pMonitor : false))
|
||||
return false;
|
||||
continue;
|
||||
}
|
||||
@@ -359,13 +364,13 @@ bool CWorkspace::matchesStaticSelector(const std::string& selector_) {
|
||||
|
||||
const auto WANTSNAMED = configStringToInt(prop);
|
||||
|
||||
if (WANTSNAMED != (m_iID <= -1337))
|
||||
if (WANTSNAMED && *WANTSNAMED != (m_iID <= -1337))
|
||||
return false;
|
||||
continue;
|
||||
}
|
||||
|
||||
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;
|
||||
@@ -378,7 +383,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++;
|
||||
@@ -414,10 +419,10 @@ bool CWorkspace::matchesStaticSelector(const std::string& selector_) {
|
||||
|
||||
int count;
|
||||
if (wantsCountGroup)
|
||||
count = g_pCompositor->getGroupsOnWorkspace(m_iID, wantsOnlyTiled == -1 ? std::nullopt : std::optional<bool>((bool)wantsOnlyTiled),
|
||||
count = getGroups(wantsOnlyTiled == -1 ? std::nullopt : std::optional<bool>((bool)wantsOnlyTiled),
|
||||
wantsCountVisible ? std::optional<bool>(wantsCountVisible) : std::nullopt);
|
||||
else
|
||||
count = g_pCompositor->getWindowsOnWorkspace(m_iID, wantsOnlyTiled == -1 ? std::nullopt : std::optional<bool>((bool)wantsOnlyTiled),
|
||||
count = getWindows(wantsOnlyTiled == -1 ? std::nullopt : std::optional<bool>((bool)wantsOnlyTiled),
|
||||
wantsCountVisible ? std::optional<bool>(wantsCountVisible) : std::nullopt);
|
||||
|
||||
if (count != from)
|
||||
@@ -425,7 +430,7 @@ bool CWorkspace::matchesStaticSelector(const std::string& selector_) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto DASHPOS = prop.find("-");
|
||||
const auto DASHPOS = prop.find('-');
|
||||
const auto LHS = prop.substr(0, DASHPOS), RHS = prop.substr(DASHPOS + 1);
|
||||
|
||||
if (!isNumber(LHS) || !isNumber(RHS)) {
|
||||
@@ -446,12 +451,12 @@ 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),
|
||||
count = getGroups(wantsOnlyTiled == -1 ? std::nullopt : std::optional<bool>((bool)wantsOnlyTiled),
|
||||
wantsCountVisible ? std::optional<bool>(wantsCountVisible) : std::nullopt);
|
||||
else
|
||||
count = g_pCompositor->getWindowsOnWorkspace(m_iID, wantsOnlyTiled == -1 ? std::nullopt : std::optional<bool>((bool)wantsOnlyTiled),
|
||||
count = getWindows(wantsOnlyTiled == -1 ? std::nullopt : std::optional<bool>((bool)wantsOnlyTiled),
|
||||
wantsCountVisible ? std::optional<bool>(wantsCountVisible) : std::nullopt);
|
||||
|
||||
if (std::clamp(count, from, to) != count)
|
||||
@@ -506,10 +511,149 @@ bool CWorkspace::matchesStaticSelector(const std::string& selector_) {
|
||||
void CWorkspace::markInert() {
|
||||
m_bInert = true;
|
||||
m_iID = WORKSPACE_INVALID;
|
||||
m_iMonitorID = -1;
|
||||
m_bVisible = false;
|
||||
m_pMonitor.reset();
|
||||
}
|
||||
|
||||
bool CWorkspace::inert() {
|
||||
return m_bInert;
|
||||
}
|
||||
|
||||
MONITORID CWorkspace::monitorID() {
|
||||
return m_pMonitor ? m_pMonitor->ID : MONITOR_INVALID;
|
||||
}
|
||||
|
||||
PHLWINDOW CWorkspace::getFullscreenWindow() {
|
||||
for (auto const& w : g_pCompositor->m_vWindows) {
|
||||
if (w->m_pWorkspace == m_pSelf && w->isFullscreen())
|
||||
return w;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool CWorkspace::isVisible() {
|
||||
return m_bVisible;
|
||||
}
|
||||
|
||||
bool CWorkspace::isVisibleNotCovered() {
|
||||
const auto PMONITOR = m_pMonitor.lock();
|
||||
if (PMONITOR->activeSpecialWorkspace)
|
||||
return PMONITOR->activeSpecialWorkspace->m_iID == m_iID;
|
||||
|
||||
return PMONITOR->activeWorkspace->m_iID == m_iID;
|
||||
}
|
||||
|
||||
int CWorkspace::getWindows(std::optional<bool> onlyTiled, std::optional<bool> onlyVisible) {
|
||||
int no = 0;
|
||||
for (auto const& w : g_pCompositor->m_vWindows) {
|
||||
if (w->workspaceID() != m_iID || !w->m_bIsMapped)
|
||||
continue;
|
||||
if (onlyTiled.has_value() && w->m_bIsFloating == onlyTiled.value())
|
||||
continue;
|
||||
if (onlyVisible.has_value() && w->isHidden() == onlyVisible.value())
|
||||
continue;
|
||||
no++;
|
||||
}
|
||||
|
||||
return no;
|
||||
}
|
||||
|
||||
int CWorkspace::getGroups(std::optional<bool> onlyTiled, std::optional<bool> onlyVisible) {
|
||||
int no = 0;
|
||||
for (auto const& w : g_pCompositor->m_vWindows) {
|
||||
if (w->workspaceID() != m_iID || !w->m_bIsMapped)
|
||||
continue;
|
||||
if (!w->m_sGroupData.head)
|
||||
continue;
|
||||
if (onlyTiled.has_value() && w->m_bIsFloating == onlyTiled.value())
|
||||
continue;
|
||||
if (onlyVisible.has_value() && w->isHidden() == onlyVisible.value())
|
||||
continue;
|
||||
no++;
|
||||
}
|
||||
return no;
|
||||
}
|
||||
|
||||
PHLWINDOW CWorkspace::getFirstWindow() {
|
||||
for (auto const& w : g_pCompositor->m_vWindows) {
|
||||
if (w->m_pWorkspace == m_pSelf && w->m_bIsMapped && !w->isHidden())
|
||||
return w;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
PHLWINDOW CWorkspace::getTopLeftWindow() {
|
||||
const auto PMONITOR = m_pMonitor.lock();
|
||||
|
||||
for (auto const& w : g_pCompositor->m_vWindows) {
|
||||
if (w->m_pWorkspace != m_pSelf || !w->m_bIsMapped || w->isHidden())
|
||||
continue;
|
||||
|
||||
const auto WINDOWIDEALBB = w->getWindowIdealBoundingBoxIgnoreReserved();
|
||||
|
||||
if (WINDOWIDEALBB.x <= PMONITOR->vecPosition.x + 1 && WINDOWIDEALBB.y <= PMONITOR->vecPosition.y + 1)
|
||||
return w;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool CWorkspace::hasUrgentWindow() {
|
||||
for (auto const& w : g_pCompositor->m_vWindows) {
|
||||
if (w->m_pWorkspace == m_pSelf && w->m_bIsMapped && w->m_bIsUrgent)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void CWorkspace::updateWindowDecos() {
|
||||
for (auto const& w : g_pCompositor->m_vWindows) {
|
||||
if (w->m_pWorkspace != m_pSelf)
|
||||
continue;
|
||||
|
||||
w->updateWindowDecos();
|
||||
}
|
||||
}
|
||||
|
||||
void CWorkspace::updateWindowData() {
|
||||
const auto WORKSPACERULE = g_pConfigManager->getWorkspaceRuleFor(m_pSelf.lock());
|
||||
|
||||
for (auto const& w : g_pCompositor->m_vWindows) {
|
||||
if (w->m_pWorkspace != m_pSelf)
|
||||
continue;
|
||||
|
||||
w->updateWindowData(WORKSPACERULE);
|
||||
}
|
||||
}
|
||||
|
||||
void CWorkspace::forceReportSizesToWindows() {
|
||||
for (auto const& w : g_pCompositor->m_vWindows) {
|
||||
if (w->m_pWorkspace != m_pSelf || !w->m_bIsMapped || w->isHidden())
|
||||
continue;
|
||||
|
||||
g_pXWaylandManager->setWindowSize(w, w->m_vRealSize.value(), true);
|
||||
}
|
||||
}
|
||||
|
||||
void CWorkspace::rename(const std::string& name) {
|
||||
if (g_pCompositor->isWorkspaceSpecial(m_iID))
|
||||
return;
|
||||
|
||||
Debug::log(LOG, "CWorkspace::rename: Renaming workspace {} to '{}'", m_iID, name);
|
||||
m_szName = name;
|
||||
|
||||
g_pEventManager->postEvent({"renameworkspace", std::to_string(m_iID) + "," + m_szName});
|
||||
}
|
||||
|
||||
void CWorkspace::updateWindows() {
|
||||
m_bHasFullscreenWindow = std::ranges::any_of(g_pCompositor->m_vWindows, [this](const auto& w) { return w->m_bIsMapped && w->m_pWorkspace == m_pSelf && w->isFullscreen(); });
|
||||
|
||||
for (auto const& w : g_pCompositor->m_vWindows) {
|
||||
if (!w->m_bIsMapped || w->m_pWorkspace != m_pSelf)
|
||||
continue;
|
||||
|
||||
w->updateDynamicRules();
|
||||
}
|
||||
}
|
||||
|
@@ -17,16 +17,16 @@ 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, PHLMONITOR monitor, 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, PHLMONITOR monitor, 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;
|
||||
PHLMONITORREF m_pMonitor;
|
||||
// Previous workspace ID and name is stored during a workspace change, allowing travel
|
||||
// to the previous workspace.
|
||||
SWorkspaceIDName m_sPrevWorkspace, m_sPrevWorkspacePerMonitor;
|
||||
@@ -57,28 +57,35 @@ class CWorkspace {
|
||||
// last monitor (used on reconnect)
|
||||
std::string m_szLastMonitor = "";
|
||||
|
||||
bool m_bWasCreatedEmtpy = true;
|
||||
bool m_bWasCreatedEmpty = true;
|
||||
|
||||
bool m_bPersistent = false;
|
||||
|
||||
// Inert: destroyed and invalid. If this is true, release the ptr you have.
|
||||
bool inert();
|
||||
|
||||
void startAnim(bool in, bool left, bool instant = false);
|
||||
void setActive(bool on);
|
||||
|
||||
void moveToMonitor(const int&);
|
||||
|
||||
void moveToMonitor(const MONITORID&);
|
||||
MONITORID monitorID();
|
||||
PHLWINDOW getLastFocusedWindow();
|
||||
void rememberPrevWorkspace(const PHLWORKSPACE& prevWorkspace);
|
||||
|
||||
std::string getConfigName();
|
||||
|
||||
bool matchesStaticSelector(const std::string& selector);
|
||||
|
||||
void markInert();
|
||||
|
||||
SWorkspaceIDName getPrevWorkspaceIDName(bool perMonitor) const;
|
||||
void updateWindowDecos();
|
||||
void updateWindowData();
|
||||
int getWindows(std::optional<bool> onlyTiled = {}, std::optional<bool> onlyVisible = {});
|
||||
int getGroups(std::optional<bool> onlyTiled = {}, std::optional<bool> onlyVisible = {});
|
||||
bool hasUrgentWindow();
|
||||
PHLWINDOW getFirstWindow();
|
||||
PHLWINDOW getTopLeftWindow();
|
||||
PHLWINDOW getFullscreenWindow();
|
||||
bool isVisible();
|
||||
bool isVisibleNotCovered();
|
||||
void rename(const std::string& name = "");
|
||||
void forceReportSizesToWindows();
|
||||
void updateWindows();
|
||||
|
||||
private:
|
||||
void init(PHLWORKSPACE self);
|
||||
|
@@ -4,14 +4,14 @@
|
||||
#include <string>
|
||||
#include "../helpers/signal/Signal.hpp"
|
||||
|
||||
enum eHIDCapabilityType : uint32_t {
|
||||
enum eHIDCapabilityType : uint8_t {
|
||||
HID_INPUT_CAPABILITY_KEYBOARD = (1 << 0),
|
||||
HID_INPUT_CAPABILITY_POINTER = (1 << 1),
|
||||
HID_INPUT_CAPABILITY_TOUCH = (1 << 2),
|
||||
HID_INPUT_CAPABILITY_TABLET = (1 << 3),
|
||||
};
|
||||
|
||||
enum eHIDType {
|
||||
enum eHIDType : uint8_t {
|
||||
HID_TYPE_UNKNOWN = 0,
|
||||
HID_TYPE_POINTER,
|
||||
HID_TYPE_KEYBOARD,
|
||||
@@ -27,7 +27,7 @@ enum eHIDType {
|
||||
*/
|
||||
class IHID {
|
||||
public:
|
||||
virtual ~IHID() {}
|
||||
virtual ~IHID() = default;
|
||||
|
||||
virtual uint32_t getCapabilities() = 0;
|
||||
virtual eHIDType getType();
|
||||
@@ -36,5 +36,5 @@ class IHID {
|
||||
CSignal destroy;
|
||||
} events;
|
||||
|
||||
std::string deviceName;
|
||||
std::string deviceName, hlName;
|
||||
};
|