mirror of
https://github.com/hyprwm/Hyprland.git
synced 2025-07-27 10:11:55 -07:00
Compare commits
133 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
0bd541f2fd | ||
|
23d00cdd0d | ||
|
061241d3a2 | ||
|
b9df70be22 | ||
|
9583429eae | ||
|
747c38112b | ||
|
508e82341f | ||
|
ec0a38303b | ||
|
d0bffc4fa9 | ||
|
07a19e2c95 | ||
|
46d5b363fa | ||
|
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 |
101
.clang-tidy
Normal file
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
|
10
.github/actions/setup_base/action.yml
vendored
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
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?
|
||||
|
||||
|
||||
|
3
.github/workflows/nix-build.yml
vendored
3
.github/workflows/nix-build.yml
vendored
@@ -12,7 +12,8 @@ jobs:
|
||||
matrix:
|
||||
package:
|
||||
- hyprland
|
||||
- hyprland-cross
|
||||
# - 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
|
||||
|
@@ -101,11 +101,17 @@ 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.2)
|
||||
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
|
||||
@@ -124,9 +130,7 @@ pkg_check_modules(
|
||||
libinput
|
||||
gbm
|
||||
gio-2.0
|
||||
hyprlang>=0.3.2
|
||||
hyprcursor>=0.1.7
|
||||
hyprutils>=0.2.3)
|
||||
re2)
|
||||
|
||||
find_package(hyprwayland-scanner 0.3.10 REQUIRED)
|
||||
|
||||
@@ -222,16 +226,15 @@ if(NO_SYSTEMD)
|
||||
else()
|
||||
message(STATUS "SYSTEMD support is requested (NO_SYSTEMD not defined)...")
|
||||
add_compile_definitions(USES_SYSTEMD)
|
||||
configure_file(systemd/hyprland-session.service.in
|
||||
systemd/hyprland-session.service @ONLY)
|
||||
|
||||
# session file -systemd
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/systemd/hyprland-systemd.desktop
|
||||
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/wayland-sessions)
|
||||
|
||||
# install systemd service
|
||||
install(FILES ${CMAKE_BINARY_DIR}/systemd/hyprland-session.service
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/systemd/user)
|
||||
# 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})
|
||||
@@ -245,7 +248,7 @@ target_precompile_headers(Hyprland PRIVATE
|
||||
|
||||
message(STATUS "Setting link libraries")
|
||||
|
||||
target_link_libraries(Hyprland rt PkgConfig::aquamarine_dep 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()
|
||||
|
3
Makefile
3
Makefile
@@ -1,5 +1,8 @@
|
||||
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
|
||||
cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
|
||||
|
@@ -136,13 +136,10 @@ animations {
|
||||
# Ref https://wiki.hyprland.org/Configuring/Workspace-Rules/
|
||||
# "Smart gaps" / "No gaps when only"
|
||||
# uncomment all if you wish to use that.
|
||||
# workspace = w[t1], gapsout:0, gapsin:0
|
||||
# workspace = w[tg1], gapsout:0, gapsin:0
|
||||
# workspace = w[tv1], gapsout:0, gapsin:0
|
||||
# workspace = f[1], gapsout:0, gapsin:0
|
||||
# windowrulev2 = bordersize 0, floating:0, onworkspace:w[t1]
|
||||
# windowrulev2 = rounding 0, floating:0, onworkspace:w[t1]
|
||||
# windowrulev2 = bordersize 0, floating:0, onworkspace:w[tg1]
|
||||
# windowrulev2 = rounding 0, floating:0, onworkspace:w[tg1]
|
||||
# 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]
|
||||
|
||||
|
96
flake.lock
generated
96
flake.lock
generated
@@ -16,11 +16,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1730968822,
|
||||
"narHash": "sha256-NocDjINsh6ismkhb0Xr6xPRksmhuB2WGf8ZmXMhxu7Y=",
|
||||
"lastModified": 1734364797,
|
||||
"narHash": "sha256-2h1c+P0v3l0Z/ypUSsAPhU/yiSRgFwjVFODWp0S3d/w=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "aquamarine",
|
||||
"rev": "a49bc3583ff223f426cb3526fdaa4bcaa247ec14",
|
||||
"rev": "8e77618b403a82fde2105a8e3cd7cabe7ef00952",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -79,11 +79,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1728669738,
|
||||
"narHash": "sha256-EDNAU9AYcx8OupUzbTbWE1d3HYdeG0wO6Msg3iL1muk=",
|
||||
"lastModified": 1734364709,
|
||||
"narHash": "sha256-+2bZJL2u5hva7rSp65OfKJBK+k03T6GB/NCvpoS1OOo=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "hyprcursor",
|
||||
"rev": "0264e698149fcb857a66a53018157b41f8d97bb0",
|
||||
"rev": "f388aacd22be4a6e4d634fbaf6f75eb0713d239a",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -92,6 +92,32 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"hyprgraphics": {
|
||||
"inputs": {
|
||||
"hyprutils": [
|
||||
"hyprutils"
|
||||
],
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
],
|
||||
"systems": [
|
||||
"systems"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1733684019,
|
||||
"narHash": "sha256-2kYREgmSmbLsmDpLEq96hxVAU3qz8aCvVhF65yCFZHY=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "hyprgraphics",
|
||||
"rev": "fb2c0268645a77403af3b8a4ce8fa7ba5917f15d",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "hyprwm",
|
||||
"repo": "hyprgraphics",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"hyprland-protocols": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
@@ -115,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": [
|
||||
@@ -128,11 +180,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1728168612,
|
||||
"narHash": "sha256-AnB1KfiXINmuiW7BALYrKqcjCnsLZPifhb/7BsfPbns=",
|
||||
"lastModified": 1734364628,
|
||||
"narHash": "sha256-ii8fzJfI953n/EmIxVvq64ZAwhvwuuPHWfGd61/mJG8=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "hyprlang",
|
||||
"rev": "f054f2e44d6a0b74607a6bc0f52dba337a3db38e",
|
||||
"rev": "16e59c1eb13d9fb6de066f54e7555eb5e8a4aba5",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -151,11 +203,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1730968903,
|
||||
"narHash": "sha256-zFvzLXcSm0Ia4XI1SE4FQ9KE63hlGrRWhLtwMolWuR8=",
|
||||
"lastModified": 1733502241,
|
||||
"narHash": "sha256-KAUNC4Dgq8WQjYov5auBw/usaHixhacvb7cRDd0AG/k=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "hyprutils",
|
||||
"rev": "3ce0cde8709cdacbfba471f8e828433b58a561e9",
|
||||
"rev": "104117aed6dd68561be38b50f218190aa47f2cd8",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -189,11 +241,11 @@
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1730785428,
|
||||
"narHash": "sha256-Zwl8YgTVJTEum+L+0zVAWvXAGbWAuXHax3KzuejaDyo=",
|
||||
"lastModified": 1734119587,
|
||||
"narHash": "sha256-AKU6qqskl0yf2+JdRdD0cfxX4b9x3KKV5RqA6wijmPM=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "4aa36568d413aca0ea84a1684d2d46f55dbabad7",
|
||||
"rev": "3566ab7246670a43abd2ffa913cc62dad9cdf7d5",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -229,11 +281,11 @@
|
||||
"nixpkgs-stable": "nixpkgs-stable"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1730814269,
|
||||
"narHash": "sha256-fWPHyhYE6xvMI1eGY3pwBTq85wcy1YXqdzTZF+06nOg=",
|
||||
"lastModified": 1734279981,
|
||||
"narHash": "sha256-NdaCraHPp8iYMWzdXAt5Nv6sA3MUzlCiGiR586TCwo0=",
|
||||
"owner": "cachix",
|
||||
"repo": "git-hooks.nix",
|
||||
"rev": "d70155fdc00df4628446352fc58adc640cd705c2",
|
||||
"rev": "aa9f40c906904ebd83da78e7f328cd8aeaeae785",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -246,7 +298,9 @@
|
||||
"inputs": {
|
||||
"aquamarine": "aquamarine",
|
||||
"hyprcursor": "hyprcursor",
|
||||
"hyprgraphics": "hyprgraphics",
|
||||
"hyprland-protocols": "hyprland-protocols",
|
||||
"hyprland-qtutils": "hyprland-qtutils",
|
||||
"hyprlang": "hyprlang",
|
||||
"hyprutils": "hyprutils",
|
||||
"hyprwayland-scanner": "hyprwayland-scanner",
|
||||
@@ -293,11 +347,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1730743262,
|
||||
"narHash": "sha256-iTLqj3lU8kFehPm5tXpctzkD274t/k1nwSSq3qCWXeg=",
|
||||
"lastModified": 1734124279,
|
||||
"narHash": "sha256-YNpFfiQjYt2o6LGcMN9NkjVvprC8ELrIpLHlbZbclRM=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "xdg-desktop-portal-hyprland",
|
||||
"rev": "09b23cef06fe248e61cec8862c04b9bcb62f4b6d",
|
||||
"rev": "0c6861f819f6d31f6195c9864709b2556f00b5cf",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
16
flake.nix
16
flake.nix
@@ -22,12 +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";
|
||||
@@ -116,13 +130,11 @@
|
||||
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;
|
||||
|
@@ -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,3 +1,5 @@
|
||||
#include <re2/re2.h>
|
||||
|
||||
#include <cctype>
|
||||
#include <netdb.h>
|
||||
#include <netinet/in.h>
|
||||
@@ -21,10 +23,8 @@
|
||||
#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>
|
||||
@@ -52,11 +52,17 @@ void log(const std::string& str) {
|
||||
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";
|
||||
}
|
||||
|
||||
@@ -66,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;
|
||||
@@ -163,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;
|
||||
@@ -233,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";
|
||||
|
||||
@@ -271,10 +282,11 @@ 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/");
|
||||
RE2::GlobalReplace(&commands, ";\\s*", ";j/");
|
||||
commands.insert(0, "j/");
|
||||
}
|
||||
|
||||
std::string rq = "[[BATCH]]" + commands;
|
||||
@@ -311,11 +323,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;
|
||||
}
|
||||
|
@@ -3,6 +3,7 @@ executable(
|
||||
'main.cpp',
|
||||
dependencies: [
|
||||
dependency('hyprutils', version: '>= 0.1.1'),
|
||||
dependency('re2', required: true)
|
||||
],
|
||||
install: true,
|
||||
)
|
||||
|
@@ -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)
|
||||
|
@@ -23,35 +23,53 @@
|
||||
#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 "";
|
||||
|
||||
result.reserve(buffer.size());
|
||||
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::println("{}", verboseString("version returned: {}", HLVERCALL));
|
||||
std::println("{}", verboseString("{} version returned: {}", running ? "running" : "installed", HLVERCALL));
|
||||
|
||||
if (!HLVERCALL.contains("Tag:")) {
|
||||
std::println(stderr, "\n{}", failureString("You don't seem to be running Hyprland."));
|
||||
@@ -82,12 +100,18 @@ SHyprlandVersion CPluginManager::getHyprlandVersion() {
|
||||
if (m_bVerbose)
|
||||
std::println("{}", verboseString("parsed commit {} at branch {} on {}, commits {}", hlcommit, hlbranch, hldate, commits));
|
||||
|
||||
ver = SHyprlandVersion{hlbranch, hlcommit, hldate, commits};
|
||||
auto ver = SHyprlandVersion{hlbranch, hlcommit, hldate, commits};
|
||||
|
||||
if (running)
|
||||
verRunning = ver;
|
||||
else
|
||||
verInstalled = ver;
|
||||
|
||||
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))
|
||||
@@ -106,7 +130,7 @@ bool CPluginManager::addNewPluginRepo(const std::string& url, const std::string&
|
||||
const auto HLVER = getHyprlandVersion();
|
||||
|
||||
if (!hasDeps()) {
|
||||
std::println(stderr, "\n{}", failureString("Could not clone the plugin repository. Dependencies not satisfied. Hyprpm requires: cmake, meson, cpio"));
|
||||
std::println(stderr, "\n{}", failureString("Could not clone the plugin repository. Dependencies not satisfied. Hyprpm requires: cmake, meson, cpio, pkg-config"));
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -145,17 +169,17 @@ 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")) {
|
||||
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::println(stderr, "\n{}", failureString("Could not prepare working dir for repo"));
|
||||
@@ -164,7 +188,7 @@ bool CPluginManager::addNewPluginRepo(const std::string& url, const std::string&
|
||||
|
||||
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::println(stderr, "\n{}", failureString("Could not clone the plugin repository. shell returned:\n{}", ret));
|
||||
@@ -275,7 +299,7 @@ bool CPluginManager::addNewPluginRepo(const std::string& url, const std::string&
|
||||
}
|
||||
|
||||
if (m_bVerbose)
|
||||
std::println("{}", verboseString("shell returned: " + out));
|
||||
std::println("{}", verboseString("shell returned: {}", out));
|
||||
|
||||
if (!std::filesystem::exists(m_szWorkingPluginDirectory + "/" + p.output)) {
|
||||
progress.printMessageAbove(failureString("Plugin {} failed to build.\n"
|
||||
@@ -347,7 +371,7 @@ 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;
|
||||
@@ -409,16 +433,16 @@ bool CPluginManager::updateHeaders(bool force) {
|
||||
|
||||
DataState::ensureStateStoreExists();
|
||||
|
||||
const auto HLVER = getHyprlandVersion();
|
||||
const auto HLVER = getHyprlandVersion(false);
|
||||
|
||||
if (!hasDeps()) {
|
||||
std::println("\n{}", failureString("Could not update. Dependencies not satisfied. Hyprpm requires: cmake, meson, cpio"));
|
||||
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) {
|
||||
@@ -433,7 +457,7 @@ 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::println("\n{}", failureString("Could not prepare working dir for hl"));
|
||||
@@ -451,12 +475,12 @@ bool CPluginManager::updateHeaders(bool force) {
|
||||
if (m_bVerbose && bShallow)
|
||||
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(failureString("Clone failed. Retrying without shallow."));
|
||||
ret = execAndGet("cd /tmp/hyprpm && git clone --recursive https://github.com/hyprwm/hyprland hyprland-" + USERNAME);
|
||||
ret = execAndGet(std::format("cd {} && git clone --recursive https://github.com/hyprwm/hyprland hyprland-{}", getTempRoot(), USERNAME));
|
||||
}
|
||||
|
||||
if (!std::filesystem::exists(WORKINGDIR + "/.git")) {
|
||||
@@ -571,7 +595,7 @@ bool CPluginManager::updatePlugins(bool forceUpdateAll) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const auto HLVER = getHyprlandVersion();
|
||||
const auto HLVER = getHyprlandVersion(false);
|
||||
|
||||
CProgressBar progress;
|
||||
progress.m_iMaxSteps = REPOS.size() * 2 + 2;
|
||||
@@ -580,7 +604,7 @@ 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 const& repo : REPOS) {
|
||||
bool update = forceUpdateAll;
|
||||
@@ -595,7 +619,7 @@ bool CPluginManager::updatePlugins(bool forceUpdateAll) {
|
||||
|
||||
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::println("{}", failureString("could not clone repo: shell returned: {}", ret));
|
||||
@@ -820,12 +844,20 @@ 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 const& p : loadedPlugins) {
|
||||
if (!enabled(p)) {
|
||||
// unload
|
||||
loadUnloadPlugin(HYPRPMPATH + repoForName(p) + "/" + p + ".so", false);
|
||||
std::println("{}", successString("Unloaded {}", p));
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -838,17 +870,28 @@ ePluginLoadStateReturn CPluginManager::ensurePluginsLoadState() {
|
||||
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::println("{}", successString("Loaded {}", p.name));
|
||||
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::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
|
||||
|
@@ -27,7 +27,8 @@ enum ePluginLoadStateReturn {
|
||||
LOADSTATE_OK = 0,
|
||||
LOADSTATE_FAIL,
|
||||
LOADSTATE_PARTIAL_FAIL,
|
||||
LOADSTATE_HEADERS_OUTDATED
|
||||
LOADSTATE_HEADERS_OUTDATED,
|
||||
LOADSTATE_HYPRLAND_UPDATED
|
||||
};
|
||||
|
||||
struct SHyprlandVersion {
|
||||
@@ -53,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);
|
||||
|
||||
|
@@ -73,7 +73,7 @@ int main(int argc, char** argv, char** envp) {
|
||||
|
||||
if (command.empty()) {
|
||||
std::println(stderr, "{}", HELP);
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
g_pPluginManager = std::make_unique<CPluginManager>();
|
||||
@@ -103,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;
|
||||
|
||||
@@ -114,6 +114,9 @@ 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)
|
||||
@@ -130,6 +133,10 @@ int main(int argc, char** argv, char** envp) {
|
||||
}
|
||||
|
||||
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") {
|
||||
@@ -158,6 +165,7 @@ int main(int argc, char** argv, char** envp) {
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
return 1;
|
||||
} else if (notify && !notifyFail) {
|
||||
g_pPluginManager->notify(ICON_OK, 0, 4000, "[hyprpm] Loaded plugins");
|
||||
}
|
||||
|
20
meson.build
20
meson.build
@@ -31,8 +31,16 @@ if cpp_compiler.check_header('execinfo.h')
|
||||
add_project_arguments('-DHAS_EXECINFO', language: 'cpp')
|
||||
endif
|
||||
|
||||
aquamarine = dependency('aquamarine', version: '>=0.4.2')
|
||||
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'))
|
||||
@@ -51,9 +59,15 @@ endif
|
||||
backtrace_dep = cpp_compiler.find_library('execinfo', required: false)
|
||||
epoll_dep = dependency('epoll-shim', required: false) # timerfd on BSDs
|
||||
|
||||
re2 = dependency('re2', required: true)
|
||||
|
||||
# Handle options
|
||||
if get_option('systemd').enabled()
|
||||
systemd = dependency('systemd')
|
||||
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
|
||||
|
@@ -1,4 +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')
|
||||
|
@@ -12,7 +12,9 @@
|
||||
cairo,
|
||||
git,
|
||||
hyprcursor,
|
||||
hyprgraphics,
|
||||
hyprland-protocols,
|
||||
hyprland-qtutils,
|
||||
hyprlang,
|
||||
hyprutils,
|
||||
hyprwayland-scanner,
|
||||
@@ -25,6 +27,7 @@
|
||||
mesa,
|
||||
pango,
|
||||
pciutils,
|
||||
re2,
|
||||
systemd,
|
||||
tomlplusplus,
|
||||
udis86-hyprland,
|
||||
@@ -64,7 +67,7 @@ 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 {
|
||||
customStdenv.mkDerivation (finalAttrs: {
|
||||
pname = "hyprland${optionalString debug "-debug"}";
|
||||
inherit version;
|
||||
|
||||
@@ -88,6 +91,7 @@ in
|
||||
DATE = date;
|
||||
DIRTY = optionalString (commit == "") "dirty";
|
||||
HASH = commit;
|
||||
TAG = "v${builtins.readFile "${finalAttrs.src}/VERSION"}";
|
||||
|
||||
depsBuildBuild = [
|
||||
pkg-config
|
||||
@@ -113,6 +117,7 @@ in
|
||||
cairo
|
||||
git
|
||||
hyprcursor
|
||||
hyprgraphics
|
||||
hyprland-protocols
|
||||
hyprlang
|
||||
hyprutils
|
||||
@@ -124,6 +129,7 @@ in
|
||||
mesa
|
||||
pango
|
||||
pciutils
|
||||
re2
|
||||
tomlplusplus
|
||||
udis86-hyprland
|
||||
wayland
|
||||
@@ -152,7 +158,7 @@ in
|
||||
(mapAttrsToList mesonEnable {
|
||||
"xwayland" = enableXWayland;
|
||||
"legacy_renderer" = legacyRenderer;
|
||||
"systemd" = withSystemd;
|
||||
"uwsm" = false;
|
||||
})
|
||||
(mapAttrsToList mesonBool {
|
||||
"b_pch" = false;
|
||||
@@ -165,6 +171,7 @@ in
|
||||
wrapProgram $out/bin/Hyprland \
|
||||
--suffix PATH : ${makeBinPath [
|
||||
binutils
|
||||
hyprland-qtutils
|
||||
pciutils
|
||||
pkgconf
|
||||
]}
|
||||
@@ -180,4 +187,4 @@ in
|
||||
platforms = lib.platforms.linux;
|
||||
mainProgram = "Hyprland";
|
||||
};
|
||||
}
|
||||
})
|
||||
|
@@ -22,7 +22,9 @@ 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
|
||||
|
@@ -1,3 +1,5 @@
|
||||
#include <re2/re2.h>
|
||||
|
||||
#include "Compositor.hpp"
|
||||
#include "debug/Log.hpp"
|
||||
#include "helpers/Splashes.hpp"
|
||||
@@ -6,6 +8,7 @@
|
||||
#include "managers/TokenManager.hpp"
|
||||
#include "managers/PointerManager.hpp"
|
||||
#include "managers/SeatManager.hpp"
|
||||
#include "managers/VersionKeeperManager.hpp"
|
||||
#include "managers/eventLoop/EventLoopManager.hpp"
|
||||
#include <aquamarine/output/Output.hpp>
|
||||
#include <bit>
|
||||
@@ -75,7 +78,7 @@ void handleUnrecoverableSignal(int sig) {
|
||||
});
|
||||
alarm(15);
|
||||
|
||||
CrashReporter::createAndSaveCrash(sig);
|
||||
NCrashReporter::createAndSaveCrash(sig);
|
||||
|
||||
abort();
|
||||
}
|
||||
@@ -87,7 +90,7 @@ void handleUserSignal(int sig) {
|
||||
}
|
||||
}
|
||||
|
||||
static LogLevel aqLevelToHl(Aquamarine::eBackendLogLevel level) {
|
||||
static eLogLevel aqLevelToHl(Aquamarine::eBackendLogLevel level) {
|
||||
switch (level) {
|
||||
case Aquamarine::eBackendLogLevel::AQ_LOG_TRACE: return TRACE;
|
||||
case Aquamarine::eBackendLogLevel::AQ_LOG_DEBUG: return LOG;
|
||||
@@ -135,9 +138,7 @@ void CCompositor::restoreNofile() {
|
||||
Debug::log(ERR, "Failed restoring NOFILE limits");
|
||||
}
|
||||
|
||||
CCompositor::CCompositor() {
|
||||
m_iHyprlandPID = getpid();
|
||||
|
||||
CCompositor::CCompositor() : m_iHyprlandPID(getpid()) {
|
||||
m_szHyprTempDataRoot = std::string{getenv("XDG_RUNTIME_DIR")} + "/hypr";
|
||||
|
||||
if (m_szHyprTempDataRoot.starts_with("/hypr")) {
|
||||
@@ -152,7 +153,7 @@ CCompositor::CCompositor() {
|
||||
std::mt19937 engine(dev());
|
||||
std::uniform_int_distribution<> distribution(0, INT32_MAX);
|
||||
|
||||
m_szInstanceSignature = std::format("{}_{}_{}", GIT_COMMIT_HASH, std::time(NULL), distribution(engine));
|
||||
m_szInstanceSignature = std::format("{}_{}_{}", GIT_COMMIT_HASH, std::time(nullptr), distribution(engine));
|
||||
|
||||
setenv("HYPRLAND_INSTANCE_SIGNATURE", m_szInstanceSignature.c_str(), true);
|
||||
|
||||
@@ -206,11 +207,21 @@ CCompositor::~CCompositor() {
|
||||
}
|
||||
|
||||
void CCompositor::setRandomSplash() {
|
||||
auto tt = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
|
||||
auto local = *localtime(&tt);
|
||||
|
||||
const auto* SPLASHES = &NSplashes::SPLASHES;
|
||||
|
||||
if (local.tm_mon + 1 == 12 && local.tm_mday >= 23 && local.tm_mday <= 27) // dec 23-27
|
||||
SPLASHES = &NSplashes::SPLASHES_CHRISTMAS;
|
||||
if ((local.tm_mon + 1 == 12 && local.tm_mday >= 29) || (local.tm_mon + 1 == 1 && local.tm_mday <= 3))
|
||||
SPLASHES = &NSplashes::SPLASHES_NEWYEAR;
|
||||
|
||||
std::random_device dev;
|
||||
std::mt19937 engine(dev());
|
||||
std::uniform_int_distribution<> distribution(0, SPLASHES.size() - 1);
|
||||
std::uniform_int_distribution<> distribution(0, SPLASHES->size() - 1);
|
||||
|
||||
m_szCurrentSplash = SPLASHES[distribution(engine)];
|
||||
m_szCurrentSplash = SPLASHES->at(distribution(engine));
|
||||
}
|
||||
|
||||
static std::vector<SP<Aquamarine::IOutput>> pendingOutputs;
|
||||
@@ -250,7 +261,7 @@ void CCompositor::initServer(std::string socketName, int socketFd) {
|
||||
// set the buffer size to 1MB to avoid disconnects due to an app hanging for a short while
|
||||
wl_display_set_default_max_buffer_size(m_sWLDisplay, 1_MB);
|
||||
|
||||
Aquamarine::SBackendOptions options;
|
||||
Aquamarine::SBackendOptions options{};
|
||||
options.logFunction = aqLog;
|
||||
|
||||
std::vector<Aquamarine::SBackendImplementationOptions> implementations;
|
||||
@@ -482,8 +493,8 @@ void CCompositor::cleanup() {
|
||||
Debug::shuttingDown = true;
|
||||
|
||||
#ifdef USES_SYSTEMD
|
||||
if (Systemd::SdBooted() > 0 && !envEnabled("HYPRLAND_NO_SD_NOTIFY"))
|
||||
Systemd::SdNotify(0, "STOPPING=1");
|
||||
if (NSystemd::sdBooted() > 0 && !envEnabled("HYPRLAND_NO_SD_NOTIFY"))
|
||||
NSystemd::sdNotify(0, "STOPPING=1");
|
||||
#endif
|
||||
|
||||
cleanEnvironment();
|
||||
@@ -635,6 +646,9 @@ void CCompositor::initManagers(eManagersInitStage stage) {
|
||||
Debug::log(LOG, "Creating the CursorManager!");
|
||||
g_pCursorManager = std::make_unique<CCursorManager>();
|
||||
|
||||
Debug::log(LOG, "Creating the VersionKeeper!");
|
||||
g_pVersionKeeperMgr = std::make_unique<CVersionKeeperManager>();
|
||||
|
||||
Debug::log(LOG, "Starting XWayland");
|
||||
g_pXWayland = std::make_unique<CXWayland>(g_pCompositor->m_bEnableXwayland);
|
||||
} break;
|
||||
@@ -701,10 +715,10 @@ void CCompositor::startCompositor() {
|
||||
g_pHyprRenderer->setCursorFromName("left_ptr");
|
||||
|
||||
#ifdef USES_SYSTEMD
|
||||
if (Systemd::SdBooted() > 0) {
|
||||
if (NSystemd::sdBooted() > 0) {
|
||||
// tell systemd that we are ready so it can start other bond, following, related units
|
||||
if (!envEnabled("HYPRLAND_NO_SD_NOTIFY"))
|
||||
Systemd::SdNotify(0, "READY=1");
|
||||
NSystemd::sdNotify(0, "READY=1");
|
||||
} else
|
||||
Debug::log(LOG, "systemd integration is baked in but system itself is not booted à la systemd!");
|
||||
#endif
|
||||
@@ -833,6 +847,9 @@ PHLWINDOW CCompositor::vectorToWindowUnified(const Vector2D& pos, uint8_t proper
|
||||
if (special && !w->onSpecialWorkspace()) // because special floating may creep up into regular
|
||||
continue;
|
||||
|
||||
if (!w->m_pWorkspace)
|
||||
continue;
|
||||
|
||||
const auto PWINDOWMONITOR = w->m_pMonitor.lock();
|
||||
|
||||
// to avoid focusing windows behind special workspaces from other monitors
|
||||
@@ -844,7 +861,7 @@ PHLWINDOW CCompositor::vectorToWindowUnified(const Vector2D& pos, uint8_t proper
|
||||
continue;
|
||||
}
|
||||
|
||||
if (w->m_bIsFloating && w->m_bIsMapped && isWorkspaceVisible(w->m_pWorkspace) && !w->isHidden() && !w->m_bPinned && !w->m_sWindowData.noFocus.valueOrDefault() &&
|
||||
if (w->m_bIsFloating && w->m_bIsMapped && w->m_pWorkspace->isVisible() && !w->isHidden() && !w->m_bPinned && !w->m_sWindowData.noFocus.valueOrDefault() &&
|
||||
w != pIgnoreWindow && (!aboveFullscreen || w->m_bCreatedOverFullscreen)) {
|
||||
// OR windows should add focus to parent
|
||||
if (w->m_bX11ShouldntFocus && !w->isX11OverrideRedirect())
|
||||
@@ -887,7 +904,7 @@ PHLWINDOW CCompositor::vectorToWindowUnified(const Vector2D& pos, uint8_t proper
|
||||
const auto PWORKSPACE = getWorkspaceByID(WSPID);
|
||||
|
||||
if (PWORKSPACE->m_bHasFullscreenWindow)
|
||||
return getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID);
|
||||
return PWORKSPACE->getFullscreenWindow();
|
||||
|
||||
auto found = floating(false);
|
||||
if (found)
|
||||
@@ -898,6 +915,9 @@ PHLWINDOW CCompositor::vectorToWindowUnified(const Vector2D& pos, uint8_t proper
|
||||
if (special != w->onSpecialWorkspace())
|
||||
continue;
|
||||
|
||||
if (!w->m_pWorkspace)
|
||||
continue;
|
||||
|
||||
if (!w->m_bIsX11 && !w->m_bIsFloating && w->m_bIsMapped && w->workspaceID() == WSPID && !w->isHidden() && !w->m_bX11ShouldntFocus &&
|
||||
!w->m_sWindowData.noFocus.valueOrDefault() && w != pIgnoreWindow) {
|
||||
if (w->hasPopupAt(pos))
|
||||
@@ -909,6 +929,9 @@ PHLWINDOW CCompositor::vectorToWindowUnified(const Vector2D& pos, uint8_t proper
|
||||
if (special != w->onSpecialWorkspace())
|
||||
continue;
|
||||
|
||||
if (!w->m_pWorkspace)
|
||||
continue;
|
||||
|
||||
if (!w->m_bIsFloating && w->m_bIsMapped && w->workspaceID() == WSPID && !w->isHidden() && !w->m_bX11ShouldntFocus && !w->m_sWindowData.noFocus.valueOrDefault() &&
|
||||
w != pIgnoreWindow) {
|
||||
CBox box = (properties & USE_PROP_TILED) ? w->getWindowBoxUnified(properties) : CBox{w->m_vPosition, w->m_vSize};
|
||||
@@ -1070,14 +1093,15 @@ void CCompositor::focusWindow(PHLWINDOW pWindow, SP<CWLSurfaceResource> pSurface
|
||||
|
||||
const auto PMONITOR = pWindow->m_pMonitor.lock();
|
||||
|
||||
if (!isWorkspaceVisible(pWindow->m_pWorkspace)) {
|
||||
if (!pWindow->m_pWorkspace || !pWindow->m_pWorkspace->isVisible()) {
|
||||
const auto PWORKSPACE = pWindow->m_pWorkspace;
|
||||
// This is to fix incorrect feedback on the focus history.
|
||||
PWORKSPACE->m_pLastFocusedWindow = pWindow;
|
||||
PWORKSPACE->rememberPrevWorkspace(m_pLastMonitor->activeWorkspace);
|
||||
if (m_pLastMonitor->activeWorkspace)
|
||||
PWORKSPACE->rememberPrevWorkspace(m_pLastMonitor->activeWorkspace);
|
||||
if (PWORKSPACE->m_bIsSpecialWorkspace)
|
||||
m_pLastMonitor->changeWorkspace(PWORKSPACE, false, true); // if special ws, open on current monitor
|
||||
else
|
||||
else if (PMONITOR)
|
||||
PMONITOR->changeWorkspace(PWORKSPACE, false, true);
|
||||
// changeworkspace already calls focusWindow
|
||||
return;
|
||||
@@ -1088,7 +1112,7 @@ void CCompositor::focusWindow(PHLWINDOW pWindow, SP<CWLSurfaceResource> pSurface
|
||||
|
||||
/* If special fallthrough is enabled, this behavior will be disabled, as I have no better idea of nicely tracking which
|
||||
window focuses are "via keybinds" and which ones aren't. */
|
||||
if (PMONITOR->activeSpecialWorkspace && PMONITOR->activeSpecialWorkspace != pWindow->m_pWorkspace && !pWindow->m_bPinned && !*PSPECIALFALLTHROUGH)
|
||||
if (PMONITOR && PMONITOR->activeSpecialWorkspace && PMONITOR->activeSpecialWorkspace != pWindow->m_pWorkspace && !pWindow->m_bPinned && !*PSPECIALFALLTHROUGH)
|
||||
PMONITOR->setSpecialWorkspace(nullptr);
|
||||
|
||||
// we need to make the PLASTWINDOW not equal to m_pLastWindow so that RENDERDATA is correct for an unfocused window
|
||||
@@ -1247,30 +1271,6 @@ PHLWINDOW CCompositor::getWindowFromHandle(uint32_t handle) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
PHLWINDOW CCompositor::getFullscreenWindowOnWorkspace(const WORKSPACEID& ID) {
|
||||
for (auto const& w : m_vWindows) {
|
||||
if (w->workspaceID() == ID && w->isFullscreen())
|
||||
return w;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool CCompositor::isWorkspaceVisible(PHLWORKSPACE w) {
|
||||
return valid(w) && w->m_bVisible;
|
||||
}
|
||||
|
||||
bool CCompositor::isWorkspaceVisibleNotCovered(PHLWORKSPACE w) {
|
||||
if (!valid(w))
|
||||
return false;
|
||||
|
||||
const auto PMONITOR = w->m_pMonitor.lock();
|
||||
if (PMONITOR->activeSpecialWorkspace)
|
||||
return PMONITOR->activeSpecialWorkspace->m_iID == w->m_iID;
|
||||
|
||||
return PMONITOR->activeWorkspace->m_iID == w->m_iID;
|
||||
}
|
||||
|
||||
PHLWORKSPACE CCompositor::getWorkspaceByID(const WORKSPACEID& id) {
|
||||
for (auto const& w : m_vWorkspaces) {
|
||||
if (w->m_iID == id && !w->inert())
|
||||
@@ -1295,37 +1295,6 @@ void CCompositor::sanityCheckWorkspaces() {
|
||||
}
|
||||
}
|
||||
|
||||
int CCompositor::getWindowsOnWorkspace(const WORKSPACEID& id, std::optional<bool> onlyTiled, std::optional<bool> onlyVisible) {
|
||||
int no = 0;
|
||||
for (auto const& w : m_vWindows) {
|
||||
if (w->workspaceID() != id || !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 CCompositor::getGroupsOnWorkspace(const WORKSPACEID& id, std::optional<bool> onlyTiled, std::optional<bool> onlyVisible) {
|
||||
int no = 0;
|
||||
for (auto const& w : m_vWindows) {
|
||||
if (w->workspaceID() != id || !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 CCompositor::getUrgentWindow() {
|
||||
for (auto const& w : m_vWindows) {
|
||||
if (w->m_bIsMapped && w->m_bIsUrgent)
|
||||
@@ -1335,44 +1304,6 @@ PHLWINDOW CCompositor::getUrgentWindow() {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool CCompositor::hasUrgentWindowOnWorkspace(const WORKSPACEID& id) {
|
||||
for (auto const& w : m_vWindows) {
|
||||
if (w->workspaceID() == id && w->m_bIsMapped && w->m_bIsUrgent)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
PHLWINDOW CCompositor::getFirstWindowOnWorkspace(const WORKSPACEID& id) {
|
||||
for (auto const& w : m_vWindows) {
|
||||
if (w->workspaceID() == id && w->m_bIsMapped && !w->isHidden())
|
||||
return w;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
PHLWINDOW CCompositor::getTopLeftWindowOnWorkspace(const WORKSPACEID& id) {
|
||||
const auto PWORKSPACE = getWorkspaceByID(id);
|
||||
|
||||
if (!PWORKSPACE)
|
||||
return nullptr;
|
||||
|
||||
const auto PMONITOR = PWORKSPACE->m_pMonitor.lock();
|
||||
|
||||
for (auto const& w : m_vWindows) {
|
||||
if (w->workspaceID() != id || !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 CCompositor::isWindowActive(PHLWINDOW pWindow) {
|
||||
if (m_pLastWindow.expired() && !m_pLastFocus)
|
||||
return false;
|
||||
@@ -1389,6 +1320,9 @@ void CCompositor::changeWindowZOrder(PHLWINDOW pWindow, bool top) {
|
||||
if (!validMapped(pWindow))
|
||||
return;
|
||||
|
||||
if (top)
|
||||
pWindow->m_bCreatedOverFullscreen = true;
|
||||
|
||||
if (pWindow == (top ? m_vWindows.back() : m_vWindows.front()))
|
||||
return;
|
||||
|
||||
@@ -1413,24 +1347,21 @@ void CCompositor::changeWindowZOrder(PHLWINDOW pWindow, bool top) {
|
||||
g_pHyprRenderer->damageMonitor(pw->m_pMonitor.lock());
|
||||
};
|
||||
|
||||
if (top)
|
||||
pWindow->m_bCreatedOverFullscreen = true;
|
||||
|
||||
if (!pWindow->m_bIsX11)
|
||||
moveToZ(pWindow, top);
|
||||
else {
|
||||
// move X11 window stack
|
||||
|
||||
std::deque<PHLWINDOW> toMove;
|
||||
std::vector<PHLWINDOW> toMove;
|
||||
|
||||
auto x11Stack = [&](PHLWINDOW pw, bool top, auto&& x11Stack) -> void {
|
||||
auto x11Stack = [&](PHLWINDOW pw, bool top, auto&& x11Stack) -> void {
|
||||
if (top)
|
||||
toMove.emplace_back(pw);
|
||||
else
|
||||
toMove.emplace_front(pw);
|
||||
toMove.insert(toMove.begin(), pw);
|
||||
|
||||
for (auto const& w : m_vWindows) {
|
||||
if (w->m_bIsMapped && !w->isHidden() && w->m_bIsX11 && w->X11TransientFor() == pw && w != pw && std::find(toMove.begin(), toMove.end(), w) == toMove.end()) {
|
||||
if (w->m_bIsMapped && !w->isHidden() && w->m_bIsX11 && w->x11TransientFor() == pw && w != pw && std::find(toMove.begin(), toMove.end(), w) == toMove.end()) {
|
||||
x11Stack(w, top, x11Stack);
|
||||
}
|
||||
}
|
||||
@@ -1438,7 +1369,7 @@ void CCompositor::changeWindowZOrder(PHLWINDOW pWindow, bool top) {
|
||||
|
||||
x11Stack(pWindow, top, x11Stack);
|
||||
|
||||
for (auto it : toMove) {
|
||||
for (const auto& it : toMove) {
|
||||
moveToZ(it, top);
|
||||
}
|
||||
}
|
||||
@@ -1560,7 +1491,7 @@ PHLWINDOW CCompositor::getWindowInDirection(PHLWINDOW pWindow, char dir) {
|
||||
|
||||
// for tiled windows, we calc edges
|
||||
for (auto const& w : m_vWindows) {
|
||||
if (w == pWindow || !w->m_bIsMapped || w->isHidden() || (!w->isFullscreen() && w->m_bIsFloating) || !isWorkspaceVisible(w->m_pWorkspace))
|
||||
if (w == pWindow || !w->m_pWorkspace || !w->m_bIsMapped || w->isHidden() || (!w->isFullscreen() && w->m_bIsFloating) || !w->m_pWorkspace->isVisible())
|
||||
continue;
|
||||
|
||||
if (pWindow->m_pMonitor == w->m_pMonitor && pWindow->m_pWorkspace != w->m_pWorkspace)
|
||||
@@ -1642,7 +1573,7 @@ PHLWINDOW CCompositor::getWindowInDirection(PHLWINDOW pWindow, char dir) {
|
||||
static const std::unordered_map<char, Vector2D> VECTORS = {{'r', {1, 0}}, {'t', {0, -1}}, {'b', {0, 1}}, {'l', {-1, 0}}};
|
||||
|
||||
//
|
||||
auto vectorAngles = [](Vector2D a, Vector2D b) -> double {
|
||||
auto vectorAngles = [](const Vector2D& a, const Vector2D& b) -> double {
|
||||
double dot = a.x * b.x + a.y * b.y;
|
||||
double ang = std::acos(dot / (a.size() * b.size()));
|
||||
return ang;
|
||||
@@ -1652,7 +1583,7 @@ PHLWINDOW CCompositor::getWindowInDirection(PHLWINDOW pWindow, char dir) {
|
||||
constexpr float THRESHOLD = 0.3 * M_PI;
|
||||
|
||||
for (auto const& w : m_vWindows) {
|
||||
if (w == pWindow || !w->m_bIsMapped || w->isHidden() || (!w->isFullscreen() && !w->m_bIsFloating) || !isWorkspaceVisible(w->m_pWorkspace))
|
||||
if (w == pWindow || !w->m_bIsMapped || !w->m_pWorkspace || w->isHidden() || (!w->isFullscreen() && !w->m_bIsFloating) || !w->m_pWorkspace->isVisible())
|
||||
continue;
|
||||
|
||||
if (pWindow->m_pMonitor == w->m_pMonitor && pWindow->m_pWorkspace != w->m_pWorkspace)
|
||||
@@ -1678,7 +1609,7 @@ PHLWINDOW CCompositor::getWindowInDirection(PHLWINDOW pWindow, char dir) {
|
||||
}
|
||||
|
||||
if (!leaderWindow && PWORKSPACE->m_bHasFullscreenWindow)
|
||||
leaderWindow = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID);
|
||||
leaderWindow = PWORKSPACE->getFullscreenWindow();
|
||||
}
|
||||
|
||||
if (leaderValue != -1)
|
||||
@@ -1871,15 +1802,6 @@ void CCompositor::updateAllWindowsAnimatedDecorationValues() {
|
||||
}
|
||||
}
|
||||
|
||||
void CCompositor::updateWorkspaceWindows(const int64_t& id) {
|
||||
for (auto const& w : m_vWindows) {
|
||||
if (!w->m_bIsMapped || w->workspaceID() != id)
|
||||
continue;
|
||||
|
||||
w->updateDynamicRules();
|
||||
}
|
||||
}
|
||||
|
||||
void CCompositor::updateWindowAnimatedDecorationValues(PHLWINDOW pWindow) {
|
||||
// optimization
|
||||
static auto PACTIVECOL = CConfigValue<Hyprlang::CUSTOMTYPE>("general:col.active_border");
|
||||
@@ -1966,11 +1888,11 @@ void CCompositor::updateWindowAnimatedDecorationValues(PHLWINDOW pWindow) {
|
||||
// shadow
|
||||
if (!pWindow->isX11OverrideRedirect() && !pWindow->m_bX11DoesntWantBorders) {
|
||||
if (pWindow == m_pLastWindow)
|
||||
pWindow->m_cRealShadowColor = CColor(*PSHADOWCOL);
|
||||
pWindow->m_cRealShadowColor = CHyprColor(*PSHADOWCOL);
|
||||
else
|
||||
pWindow->m_cRealShadowColor = CColor(*PSHADOWCOLINACTIVE != INT64_MAX ? *PSHADOWCOLINACTIVE : *PSHADOWCOL);
|
||||
pWindow->m_cRealShadowColor = CHyprColor(*PSHADOWCOLINACTIVE != INT64_MAX ? *PSHADOWCOLINACTIVE : *PSHADOWCOL);
|
||||
} else {
|
||||
pWindow->m_cRealShadowColor.setValueAndWarp(CColor(0, 0, 0, 0)); // no shadow
|
||||
pWindow->m_cRealShadowColor.setValueAndWarp(CHyprColor(0, 0, 0, 0)); // no shadow
|
||||
}
|
||||
|
||||
pWindow->updateWindowDecos();
|
||||
@@ -2325,20 +2247,21 @@ void CCompositor::changeWindowFullscreenModeClient(const PHLWINDOW PWINDOW, cons
|
||||
|
||||
void CCompositor::setWindowFullscreenInternal(const PHLWINDOW PWINDOW, const eFullscreenMode MODE) {
|
||||
if (PWINDOW->m_sWindowData.syncFullscreen.valueOrDefault())
|
||||
setWindowFullscreenState(PWINDOW, sFullscreenState{.internal = MODE, .client = MODE});
|
||||
setWindowFullscreenState(PWINDOW, SFullscreenState{.internal = MODE, .client = MODE});
|
||||
else
|
||||
setWindowFullscreenState(PWINDOW, sFullscreenState{.internal = MODE, .client = PWINDOW->m_sFullscreenState.client});
|
||||
setWindowFullscreenState(PWINDOW, SFullscreenState{.internal = MODE, .client = PWINDOW->m_sFullscreenState.client});
|
||||
}
|
||||
|
||||
void CCompositor::setWindowFullscreenClient(const PHLWINDOW PWINDOW, const eFullscreenMode MODE) {
|
||||
if (PWINDOW->m_sWindowData.syncFullscreen.valueOrDefault())
|
||||
setWindowFullscreenState(PWINDOW, sFullscreenState{.internal = MODE, .client = MODE});
|
||||
setWindowFullscreenState(PWINDOW, SFullscreenState{.internal = MODE, .client = MODE});
|
||||
else
|
||||
setWindowFullscreenState(PWINDOW, sFullscreenState{.internal = PWINDOW->m_sFullscreenState.internal, .client = MODE});
|
||||
setWindowFullscreenState(PWINDOW, SFullscreenState{.internal = PWINDOW->m_sFullscreenState.internal, .client = MODE});
|
||||
}
|
||||
|
||||
void CCompositor::setWindowFullscreenState(const PHLWINDOW PWINDOW, sFullscreenState state) {
|
||||
static auto PDIRECTSCANOUT = CConfigValue<Hyprlang::INT>("render:direct_scanout");
|
||||
void CCompositor::setWindowFullscreenState(const PHLWINDOW PWINDOW, SFullscreenState state) {
|
||||
static auto PDIRECTSCANOUT = CConfigValue<Hyprlang::INT>("render:direct_scanout");
|
||||
static auto PALLOWPINFULLSCREEN = CConfigValue<Hyprlang::INT>("binds:allow_pin_fullscreen");
|
||||
|
||||
if (!validMapped(PWINDOW) || g_pCompositor->m_bUnsafeState)
|
||||
return;
|
||||
@@ -2352,7 +2275,20 @@ void CCompositor::setWindowFullscreenState(const PHLWINDOW PWINDOW, sFullscreenS
|
||||
const eFullscreenMode CURRENT_EFFECTIVE_MODE = (eFullscreenMode)std::bit_floor((uint8_t)PWINDOW->m_sFullscreenState.internal);
|
||||
const eFullscreenMode EFFECTIVE_MODE = (eFullscreenMode)std::bit_floor((uint8_t)state.internal);
|
||||
|
||||
const bool CHANGEINTERNAL = !(PWINDOW->m_bPinned || CURRENT_EFFECTIVE_MODE == EFFECTIVE_MODE || (PWORKSPACE->m_bHasFullscreenWindow && !PWINDOW->isFullscreen()));
|
||||
if (*PALLOWPINFULLSCREEN && !PWINDOW->m_bPinFullscreened && !PWINDOW->isFullscreen() && PWINDOW->m_bPinned) {
|
||||
PWINDOW->m_bPinned = false;
|
||||
PWINDOW->m_bPinFullscreened = true;
|
||||
}
|
||||
|
||||
if (PWORKSPACE->m_bHasFullscreenWindow && !PWINDOW->isFullscreen())
|
||||
setWindowFullscreenInternal(PWORKSPACE->getFullscreenWindow(), FSMODE_NONE);
|
||||
|
||||
const bool CHANGEINTERNAL = !(PWINDOW->m_bPinned || CURRENT_EFFECTIVE_MODE == EFFECTIVE_MODE);
|
||||
|
||||
if (*PALLOWPINFULLSCREEN && PWINDOW->m_bPinFullscreened && PWINDOW->isFullscreen() && !PWINDOW->m_bPinned && state.internal == FSMODE_NONE) {
|
||||
PWINDOW->m_bPinned = true;
|
||||
PWINDOW->m_bPinFullscreened = false;
|
||||
}
|
||||
|
||||
// TODO: update the state on syncFullscreen changes
|
||||
if (!CHANGEINTERNAL && PWINDOW->m_sWindowData.syncFullscreen.valueOrDefault())
|
||||
@@ -2391,7 +2327,7 @@ void CCompositor::setWindowFullscreenState(const PHLWINDOW PWINDOW, sFullscreenS
|
||||
|
||||
g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goal(), true);
|
||||
|
||||
forceReportSizesToWindowsOnWorkspace(PWINDOW->workspaceID());
|
||||
PWORKSPACE->forceReportSizesToWindows();
|
||||
|
||||
g_pInputManager->recheckIdleInhibitorStatus();
|
||||
|
||||
@@ -2422,27 +2358,6 @@ PHLWINDOW CCompositor::getX11Parent(PHLWINDOW pWindow) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void CCompositor::updateWorkspaceWindowDecos(const WORKSPACEID& id) {
|
||||
for (auto const& w : m_vWindows) {
|
||||
if (w->workspaceID() != id)
|
||||
continue;
|
||||
|
||||
w->updateWindowDecos();
|
||||
}
|
||||
}
|
||||
|
||||
void CCompositor::updateWorkspaceWindowData(const WORKSPACEID& id) {
|
||||
const auto PWORKSPACE = getWorkspaceByID(id);
|
||||
const auto WORKSPACERULE = PWORKSPACE ? g_pConfigManager->getWorkspaceRuleFor(PWORKSPACE) : SWorkspaceRule{};
|
||||
|
||||
for (auto const& w : m_vWindows) {
|
||||
if (w->workspaceID() != id)
|
||||
continue;
|
||||
|
||||
w->updateWindowData(WORKSPACERULE);
|
||||
}
|
||||
}
|
||||
|
||||
void CCompositor::scheduleFrameForMonitor(PHLMONITOR pMonitor, IOutput::scheduleFrameReason reason) {
|
||||
if ((m_pAqBackend->hasSession() && !m_pAqBackend->session->active) || !m_bSessionActive)
|
||||
return;
|
||||
@@ -2480,19 +2395,19 @@ PHLWINDOW CCompositor::getWindowByRegex(const std::string& regexp_) {
|
||||
|
||||
eFocusWindowMode mode = MODE_CLASS_REGEX;
|
||||
|
||||
std::regex regexCheck(regexp_);
|
||||
std::string regexCheck;
|
||||
std::string matchCheck;
|
||||
if (regexp.starts_with("class:")) {
|
||||
regexCheck = std::regex(regexp.substr(6));
|
||||
regexCheck = regexp.substr(6);
|
||||
} else if (regexp.starts_with("initialclass:")) {
|
||||
mode = MODE_INITIAL_CLASS_REGEX;
|
||||
regexCheck = std::regex(regexp.substr(13));
|
||||
regexCheck = regexp.substr(13);
|
||||
} else if (regexp.starts_with("title:")) {
|
||||
mode = MODE_TITLE_REGEX;
|
||||
regexCheck = std::regex(regexp.substr(6));
|
||||
regexCheck = regexp.substr(6);
|
||||
} else if (regexp.starts_with("initialtitle:")) {
|
||||
mode = MODE_INITIAL_TITLE_REGEX;
|
||||
regexCheck = std::regex(regexp.substr(13));
|
||||
regexCheck = regexp.substr(13);
|
||||
} else if (regexp.starts_with("address:")) {
|
||||
mode = MODE_ADDRESS;
|
||||
matchCheck = regexp.substr(8);
|
||||
@@ -2508,25 +2423,25 @@ PHLWINDOW CCompositor::getWindowByRegex(const std::string& regexp_) {
|
||||
switch (mode) {
|
||||
case MODE_CLASS_REGEX: {
|
||||
const auto windowClass = w->m_szClass;
|
||||
if (!std::regex_search(windowClass, regexCheck))
|
||||
if (!RE2::FullMatch(windowClass, regexCheck))
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
case MODE_INITIAL_CLASS_REGEX: {
|
||||
const auto initialWindowClass = w->m_szInitialClass;
|
||||
if (!std::regex_search(initialWindowClass, regexCheck))
|
||||
if (!RE2::FullMatch(initialWindowClass, regexCheck))
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
case MODE_TITLE_REGEX: {
|
||||
const auto windowTitle = w->m_szTitle;
|
||||
if (!std::regex_search(windowTitle, regexCheck))
|
||||
if (!RE2::FullMatch(windowTitle, regexCheck))
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
case MODE_INITIAL_TITLE_REGEX: {
|
||||
const auto initialWindowTitle = w->m_szInitialTitle;
|
||||
if (!std::regex_search(initialWindowTitle, regexCheck))
|
||||
if (!RE2::FullMatch(initialWindowTitle, regexCheck))
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
@@ -2654,16 +2569,8 @@ Vector2D CCompositor::parseWindowVectorArgsRelative(const std::string& args, con
|
||||
return Vector2D(X, Y);
|
||||
}
|
||||
|
||||
void CCompositor::forceReportSizesToWindowsOnWorkspace(const WORKSPACEID& wid) {
|
||||
for (auto const& w : m_vWindows) {
|
||||
if (w->workspaceID() == wid && w->m_bIsMapped && !w->isHidden()) {
|
||||
g_pXWaylandManager->setWindowSize(w, w->m_vRealSize.value(), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PHLWORKSPACE CCompositor::createNewWorkspace(const WORKSPACEID& id, const MONITORID& monid, const std::string& name, bool isEmpty) {
|
||||
const auto NAME = name == "" ? std::to_string(id) : name;
|
||||
const auto NAME = name.empty() ? std::to_string(id) : name;
|
||||
auto monID = monid;
|
||||
|
||||
// check if bound
|
||||
@@ -2679,21 +2586,6 @@ PHLWORKSPACE CCompositor::createNewWorkspace(const WORKSPACEID& id, const MONITO
|
||||
return PWORKSPACE;
|
||||
}
|
||||
|
||||
void CCompositor::renameWorkspace(const WORKSPACEID& id, const std::string& name) {
|
||||
const auto PWORKSPACE = getWorkspaceByID(id);
|
||||
|
||||
if (!PWORKSPACE)
|
||||
return;
|
||||
|
||||
if (isWorkspaceSpecial(id))
|
||||
return;
|
||||
|
||||
Debug::log(LOG, "renameWorkspace: Renaming workspace {} to '{}'", id, name);
|
||||
PWORKSPACE->m_szName = name;
|
||||
|
||||
g_pEventManager->postEvent({"renameworkspace", std::to_string(PWORKSPACE->m_iID) + "," + PWORKSPACE->m_szName});
|
||||
}
|
||||
|
||||
void CCompositor::setActiveMonitor(PHLMONITOR pMonitor) {
|
||||
if (m_pLastMonitor == pMonitor)
|
||||
return;
|
||||
@@ -2726,7 +2618,8 @@ WORKSPACEID CCompositor::getNewSpecialID() {
|
||||
}
|
||||
|
||||
void CCompositor::performUserChecks() {
|
||||
static auto PNOCHECKXDG = CConfigValue<Hyprlang::INT>("misc:disable_xdg_env_checks");
|
||||
static auto PNOCHECKXDG = CConfigValue<Hyprlang::INT>("misc:disable_xdg_env_checks");
|
||||
static auto PNOCHECKQTUTILS = CConfigValue<Hyprlang::INT>("misc:disable_hyprland_qtutils_check");
|
||||
|
||||
if (!*PNOCHECKXDG) {
|
||||
const auto CURRENT_DESKTOP_ENV = getenv("XDG_CURRENT_DESKTOP");
|
||||
@@ -2734,14 +2627,21 @@ void CCompositor::performUserChecks() {
|
||||
g_pHyprNotificationOverlay->addNotification(
|
||||
std::format("Your XDG_CURRENT_DESKTOP environment seems to be managed externally, and the current value is {}.\nThis might cause issues unless it's intentional.",
|
||||
CURRENT_DESKTOP_ENV ? CURRENT_DESKTOP_ENV : "unset"),
|
||||
CColor{}, 15000, ICON_WARNING);
|
||||
CHyprColor{}, 15000, ICON_WARNING);
|
||||
}
|
||||
}
|
||||
|
||||
if (!*PNOCHECKQTUTILS) {
|
||||
if (!executableExistsInPath("hyprland-dialog")) {
|
||||
g_pHyprNotificationOverlay->addNotification(
|
||||
"Your system does not have hyprland-qtutils installed. This is a runtime dependency for some dialogs. Consider installing it.", CHyprColor{}, 15000, ICON_WARNING);
|
||||
}
|
||||
}
|
||||
|
||||
if (g_pHyprOpenGL->failedAssetsNo > 0) {
|
||||
g_pHyprNotificationOverlay->addNotification(std::format("Hyprland failed to load {} essential asset{}, blame your distro's packager for doing a bad job at packaging!",
|
||||
g_pHyprOpenGL->failedAssetsNo, g_pHyprOpenGL->failedAssetsNo > 1 ? "s" : ""),
|
||||
CColor{1.0, 0.1, 0.1, 1.0}, 15000, ICON_ERROR);
|
||||
CHyprColor{1.0, 0.1, 0.1, 1.0}, 15000, ICON_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2758,8 +2658,8 @@ void CCompositor::moveWindowToWorkspaceSafe(PHLWINDOW pWindow, PHLWORKSPACE pWor
|
||||
if (FULLSCREEN)
|
||||
setWindowFullscreenInternal(pWindow, FSMODE_NONE);
|
||||
|
||||
const PHLWINDOW pFirstWindowOnWorkspace = g_pCompositor->getFirstWindowOnWorkspace(pWorkspace->m_iID);
|
||||
const int visibleWindowsOnWorkspace = g_pCompositor->getWindowsOnWorkspace(pWorkspace->m_iID, std::nullopt, true);
|
||||
const PHLWINDOW pFirstWindowOnWorkspace = pWorkspace->getFirstWindow();
|
||||
const int visibleWindowsOnWorkspace = pWorkspace->getWindows(std::nullopt, true);
|
||||
const auto PWINDOWMONITOR = pWindow->m_pMonitor.lock();
|
||||
const auto POSTOMON = pWindow->m_vRealPosition.goal() - PWINDOWMONITOR->vecPosition;
|
||||
const auto PWORKSPACEMONITOR = pWorkspace->m_pMonitor.lock();
|
||||
@@ -2817,14 +2717,15 @@ void CCompositor::moveWindowToWorkspaceSafe(PHLWINDOW pWindow, PHLWORKSPACE pWor
|
||||
if (FULLSCREEN)
|
||||
setWindowFullscreenInternal(pWindow, FULLSCREENMODE);
|
||||
|
||||
g_pCompositor->updateWorkspaceWindows(pWorkspace->m_iID);
|
||||
g_pCompositor->updateWorkspaceWindows(pWindow->workspaceID());
|
||||
pWorkspace->updateWindows();
|
||||
if (pWindow->m_pWorkspace)
|
||||
pWindow->m_pWorkspace->updateWindows();
|
||||
g_pCompositor->updateSuspendedStates();
|
||||
}
|
||||
|
||||
PHLWINDOW CCompositor::getForceFocus() {
|
||||
for (auto const& w : m_vWindows) {
|
||||
if (!w->m_bIsMapped || w->isHidden() || !isWorkspaceVisible(w->m_pWorkspace))
|
||||
if (!w->m_bIsMapped || w->isHidden() || !w->m_pWorkspace || !w->m_pWorkspace->isVisible())
|
||||
continue;
|
||||
|
||||
if (!w->m_bStayFocused)
|
||||
@@ -2868,50 +2769,48 @@ void CCompositor::arrangeMonitors() {
|
||||
}
|
||||
|
||||
// Variables to store the max and min values of monitors on each axis.
|
||||
int maxXOffsetRight = 0;
|
||||
int maxXOffsetLeft = 0;
|
||||
int maxYOffsetUp = 0;
|
||||
int maxYOffsetDown = 0;
|
||||
int maxXOffsetRight = 0;
|
||||
int maxXOffsetLeft = 0;
|
||||
int maxYOffsetUp = 0;
|
||||
int maxYOffsetDown = 0;
|
||||
|
||||
// Finds the max and min values of explicitely placed monitors.
|
||||
for (auto const& m : arranged) {
|
||||
if (m->vecPosition.x + m->vecSize.x > maxXOffsetRight)
|
||||
maxXOffsetRight = m->vecPosition.x + m->vecSize.x;
|
||||
if (m->vecPosition.x < maxXOffsetLeft)
|
||||
maxXOffsetLeft = m->vecPosition.x;
|
||||
if (m->vecPosition.y + m->vecSize.y > maxYOffsetDown)
|
||||
maxYOffsetDown = m->vecPosition.y + m->vecSize.y;
|
||||
if (m->vecPosition.y < maxYOffsetUp)
|
||||
maxYOffsetUp = m->vecPosition.y;
|
||||
}
|
||||
auto recalcMaxOffsets = [&]() {
|
||||
maxXOffsetRight = 0;
|
||||
maxXOffsetLeft = 0;
|
||||
maxYOffsetUp = 0;
|
||||
maxYOffsetDown = 0;
|
||||
|
||||
// Finds the max and min values of explicitely placed monitors.
|
||||
for (auto const& m : arranged) {
|
||||
if (m->vecPosition.x + m->vecSize.x > maxXOffsetRight)
|
||||
maxXOffsetRight = m->vecPosition.x + m->vecSize.x;
|
||||
if (m->vecPosition.x < maxXOffsetLeft)
|
||||
maxXOffsetLeft = m->vecPosition.x;
|
||||
if (m->vecPosition.y + m->vecSize.y > maxYOffsetDown)
|
||||
maxYOffsetDown = m->vecPosition.y + m->vecSize.y;
|
||||
if (m->vecPosition.y < maxYOffsetUp)
|
||||
maxYOffsetUp = m->vecPosition.y;
|
||||
}
|
||||
};
|
||||
|
||||
// Iterates through all non-explicitly placed monitors.
|
||||
for (auto const& m : toArrange) {
|
||||
recalcMaxOffsets();
|
||||
|
||||
// Moves the monitor to their appropriate position on the x/y axis and
|
||||
// increments/decrements the corresponding max offset.
|
||||
Vector2D newPosition = {0, 0};
|
||||
switch (m->activeMonitorRule.autoDir) {
|
||||
case eAutoDirs::DIR_AUTO_UP:
|
||||
newPosition.y = maxYOffsetUp - m->vecSize.y;
|
||||
maxYOffsetUp = newPosition.y;
|
||||
break;
|
||||
case eAutoDirs::DIR_AUTO_DOWN:
|
||||
newPosition.y = maxYOffsetDown;
|
||||
maxYOffsetDown += m->vecSize.y;
|
||||
break;
|
||||
case eAutoDirs::DIR_AUTO_LEFT:
|
||||
newPosition.x = maxXOffsetLeft - m->vecSize.x;
|
||||
maxXOffsetLeft = newPosition.x;
|
||||
break;
|
||||
case eAutoDirs::DIR_AUTO_UP: newPosition.y = maxYOffsetUp - m->vecSize.y; break;
|
||||
case eAutoDirs::DIR_AUTO_DOWN: newPosition.y = maxYOffsetDown; break;
|
||||
case eAutoDirs::DIR_AUTO_LEFT: newPosition.x = maxXOffsetLeft - m->vecSize.x; break;
|
||||
case eAutoDirs::DIR_AUTO_RIGHT:
|
||||
case eAutoDirs::DIR_AUTO_NONE:
|
||||
newPosition.x = maxXOffsetRight;
|
||||
maxXOffsetRight += m->vecSize.x;
|
||||
break;
|
||||
case eAutoDirs::DIR_AUTO_NONE: newPosition.x = maxXOffsetRight; break;
|
||||
default: UNREACHABLE();
|
||||
}
|
||||
Debug::log(LOG, "arrangeMonitors: {} auto {:j}", m->szName, m->vecPosition);
|
||||
m->moveTo(newPosition);
|
||||
arranged.emplace_back(m);
|
||||
}
|
||||
|
||||
// reset maxXOffsetRight (reuse)
|
||||
@@ -3002,7 +2901,7 @@ void CCompositor::updateSuspendedStates() {
|
||||
if (!w->m_bIsMapped)
|
||||
continue;
|
||||
|
||||
w->setSuspended(w->isHidden() || !isWorkspaceVisible(w->m_pWorkspace));
|
||||
w->setSuspended(w->isHidden() || !w->m_pWorkspace || !w->m_pWorkspace->isVisible());
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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
|
||||
@@ -115,21 +114,11 @@ class CCompositor {
|
||||
PHLMONITOR getRealMonitorFromOutput(SP<Aquamarine::IOutput>);
|
||||
PHLWINDOW getWindowFromSurface(SP<CWLSurfaceResource>);
|
||||
PHLWINDOW getWindowFromHandle(uint32_t);
|
||||
bool isWorkspaceVisible(PHLWORKSPACE);
|
||||
bool isWorkspaceVisibleNotCovered(PHLWORKSPACE);
|
||||
PHLWORKSPACE getWorkspaceByID(const WORKSPACEID&);
|
||||
PHLWORKSPACE getWorkspaceByName(const std::string&);
|
||||
PHLWORKSPACE getWorkspaceByString(const std::string&);
|
||||
void sanityCheckWorkspaces();
|
||||
void updateWorkspaceWindowDecos(const WORKSPACEID&);
|
||||
void updateWorkspaceWindowData(const WORKSPACEID&);
|
||||
int getWindowsOnWorkspace(const WORKSPACEID& id, std::optional<bool> onlyTiled = {}, std::optional<bool> onlyVisible = {});
|
||||
int getGroupsOnWorkspace(const WORKSPACEID& id, std::optional<bool> onlyTiled = {}, std::optional<bool> onlyVisible = {});
|
||||
PHLWINDOW getUrgentWindow();
|
||||
bool hasUrgentWindowOnWorkspace(const WORKSPACEID&);
|
||||
PHLWINDOW getFirstWindowOnWorkspace(const WORKSPACEID&);
|
||||
PHLWINDOW getTopLeftWindowOnWorkspace(const WORKSPACEID&);
|
||||
PHLWINDOW getFullscreenWindowOnWorkspace(const WORKSPACEID&);
|
||||
bool isWindowActive(PHLWINDOW);
|
||||
void changeWindowZOrder(PHLWINDOW, bool);
|
||||
void cleanupFadingOut(const MONITORID& monid);
|
||||
@@ -142,7 +131,6 @@ class CCompositor {
|
||||
PHLMONITOR getMonitorInDirection(const char&);
|
||||
PHLMONITOR getMonitorInDirection(PHLMONITOR, const char&);
|
||||
void updateAllWindowsAnimatedDecorationValues();
|
||||
void updateWorkspaceWindows(const WORKSPACEID& id);
|
||||
void updateWindowAnimatedDecorationValues(PHLWINDOW);
|
||||
MONITORID getNextAvailableMonitorID(std::string const& name);
|
||||
void moveWorkspaceToMonitor(PHLWORKSPACE, PHLMONITOR, bool noWarpCursor = false);
|
||||
@@ -151,7 +139,7 @@ class CCompositor {
|
||||
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);
|
||||
@@ -165,10 +153,8 @@ class CCompositor {
|
||||
PHLLS getLayerSurfaceFromSurface(SP<CWLSurfaceResource>);
|
||||
void closeWindow(PHLWINDOW);
|
||||
Vector2D parseWindowVectorArgsRelative(const std::string&, const Vector2D&);
|
||||
void forceReportSizesToWindowsOnWorkspace(const WORKSPACEID&);
|
||||
PHLWORKSPACE createNewWorkspace(const WORKSPACEID&, const MONITORID&, const std::string& name = "",
|
||||
bool isEmpty = true); // will be deleted next frame if left empty and unfocused!
|
||||
void renameWorkspace(const WORKSPACEID&, const std::string& name = "");
|
||||
void setActiveMonitor(PHLMONITOR);
|
||||
bool isWorkspaceSpecial(const WORKSPACEID&);
|
||||
WORKSPACEID getNewSpecialID();
|
||||
|
@@ -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
|
||||
};
|
||||
|
@@ -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;
|
||||
|
@@ -268,7 +268,7 @@ inline static const std::vector<SConfigOptionDescription> CONFIG_OPTIONS = {
|
||||
.value = "blur:ignore_opacity",
|
||||
.description = "make the blur layer ignore the opacity of the window",
|
||||
.type = CONFIG_OPTION_BOOL,
|
||||
.data = SConfigOptionDescription::SBoolData{false},
|
||||
.data = SConfigOptionDescription::SBoolData{true},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "blur:new_optimizations",
|
||||
@@ -331,6 +331,18 @@ inline static const std::vector<SConfigOptionDescription> CONFIG_OPTIONS = {
|
||||
.type = CONFIG_OPTION_FLOAT,
|
||||
.data = SConfigOptionDescription::SFloatData{0.2, 0, 1},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "blur:input_methods",
|
||||
.description = "whether to blur input methods (e.g. fcitx5)",
|
||||
.type = CONFIG_OPTION_BOOL,
|
||||
.data = SConfigOptionDescription::SBoolData{false},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "blur:input_methods_ignorealpha",
|
||||
.description = "works like ignorealpha in layer rules. If pixel opacity is below set value, will not blur. [0.0 - 1.0]",
|
||||
.type = CONFIG_OPTION_FLOAT,
|
||||
.data = SConfigOptionDescription::SFloatData{0.2, 0, 1},
|
||||
},
|
||||
|
||||
/*
|
||||
* animations:
|
||||
@@ -620,16 +632,22 @@ inline static const std::vector<SConfigOptionDescription> CONFIG_OPTIONS = {
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "input:tablet:output",
|
||||
.description = "the monitor to bind tablets. Empty means unbound..",
|
||||
.description = "the monitor to bind tablets. Can be current or a monitor name. Leave empty to map across all monitors.",
|
||||
.type = CONFIG_OPTION_STRING_SHORT,
|
||||
.data = SConfigOptionDescription::SStringData{""}, //##TODO UNSET?
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "input:tablet:region_position",
|
||||
.description = "position of the mapped region in monitor layout.",
|
||||
.description = "position of the mapped region in monitor layout relative to the top left corner of the bound monitor or all monitors.",
|
||||
.type = CONFIG_OPTION_VECTOR,
|
||||
.data = SConfigOptionDescription::SVectorData{{}, {-20000, -20000}, {20000, 20000}},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "input:tablet:absolute_region_position",
|
||||
.description = "whether to treat the region_position as an absolute position in monitor layout. Only applies when output is empty.",
|
||||
.type = CONFIG_OPTION_BOOL,
|
||||
.data = SConfigOptionDescription::SBoolData{false},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "input:tablet:region_size",
|
||||
.description = "size of the mapped region. When this variable is set, tablet input will be mapped to the region. [0, 0] or invalid size means unset.",
|
||||
@@ -1115,6 +1133,18 @@ inline static const std::vector<SConfigOptionDescription> CONFIG_OPTIONS = {
|
||||
.type = CONFIG_OPTION_BOOL,
|
||||
.data = SConfigOptionDescription::SBoolData{false},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "misc:disable_hyprland_qtutils_check",
|
||||
.description = "disable the warning if hyprland-qtutils is missing",
|
||||
.type = CONFIG_OPTION_BOOL,
|
||||
.data = SConfigOptionDescription::SBoolData{false},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "misc:lockdead_screen_delay",
|
||||
.description = "the delay in ms after the lockdead screen appears if the lock screen did not appear after a lock event occurred.",
|
||||
.type = CONFIG_OPTION_INT,
|
||||
.data = SConfigOptionDescription::SRangeData{1000, 0, 5000},
|
||||
},
|
||||
|
||||
/*
|
||||
* binds:
|
||||
@@ -1170,6 +1200,12 @@ inline static const std::vector<SConfigOptionDescription> CONFIG_OPTIONS = {
|
||||
.type = CONFIG_OPTION_BOOL,
|
||||
.data = SConfigOptionDescription::SBoolData{true},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "binds:movefocus_cycles_groupfirst",
|
||||
.description = "If enabled, when in a grouped window, movefocus will cycle windows in the groups first, then at each ends of tabs, it'll move on to other windows/groups",
|
||||
.type = CONFIG_OPTION_BOOL,
|
||||
.data = SConfigOptionDescription::SBoolData{false},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "binds:disable_keybind_grabbing",
|
||||
.description = "If enabled, apps that request keybinds to be disabled (e.g. VMs) will not be able to do so.",
|
||||
@@ -1182,6 +1218,12 @@ inline static const std::vector<SConfigOptionDescription> CONFIG_OPTIONS = {
|
||||
.type = CONFIG_OPTION_BOOL,
|
||||
.data = SConfigOptionDescription::SBoolData{true},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "binds:allow_pin_fullscreen",
|
||||
.description = "Allows fullscreen to pinned windows, and restore their pinned status afterwards",
|
||||
.type = CONFIG_OPTION_BOOL,
|
||||
.data = SConfigOptionDescription::SBoolData{false},
|
||||
},
|
||||
|
||||
/*
|
||||
* xwayland:
|
||||
@@ -1303,9 +1345,9 @@ inline static const std::vector<SConfigOptionDescription> CONFIG_OPTIONS = {
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "cursor:warp_on_change_workspace",
|
||||
.description = "If true, move the cursor to the last focused window after changing the workspace.",
|
||||
.type = CONFIG_OPTION_BOOL,
|
||||
.data = SConfigOptionDescription::SBoolData{false},
|
||||
.description = "Move the cursor to the last focused window after changing the workspace. Options: 0 (Disabled), 1 (Enabled), 2 (Force - ignores cursor:no_warps option)",
|
||||
.type = CONFIG_OPTION_CHOICE,
|
||||
.data = SConfigOptionDescription::SChoiceData{0, "Disabled,Enabled,Force"},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "cursor:default_monitor",
|
||||
@@ -1344,8 +1386,8 @@ inline static const std::vector<SConfigOptionDescription> CONFIG_OPTIONS = {
|
||||
.data = SConfigOptionDescription::SBoolData{true},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "cursor:allow_dumb_copy",
|
||||
.description = "Makes HW cursors work on Nvidia, at the cost of a possible hitch whenever the image changes",
|
||||
.value = "cursor:use_cpu_buffer",
|
||||
.description = "Makes HW cursors use a CPU buffer. Required on Nvidia to have HW cursors. Experimental",
|
||||
.type = CONFIG_OPTION_BOOL,
|
||||
.data = SConfigOptionDescription::SBoolData{false},
|
||||
},
|
||||
@@ -1566,6 +1608,12 @@ inline static const std::vector<SConfigOptionDescription> CONFIG_OPTIONS = {
|
||||
.type = CONFIG_OPTION_BOOL,
|
||||
.data = SConfigOptionDescription::SBoolData{false},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "master:center_ignores_reserved",
|
||||
.description = "centers the master window on monitor ignoring reserved areas",
|
||||
.type = CONFIG_OPTION_BOOL,
|
||||
.data = SConfigOptionDescription::SBoolData{false},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "master:smart_resizing",
|
||||
.description =
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -8,9 +8,7 @@
|
||||
#include "../defines.hpp"
|
||||
#include <variant>
|
||||
#include <vector>
|
||||
#include <deque>
|
||||
#include <algorithm>
|
||||
#include <regex>
|
||||
#include <optional>
|
||||
#include <functional>
|
||||
#include <xf86drmMode.h>
|
||||
@@ -69,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 = "";
|
||||
};
|
||||
|
||||
@@ -84,7 +82,7 @@ struct SExecRequestedRule {
|
||||
uint64_t iPid = 0;
|
||||
};
|
||||
|
||||
enum eConfigOptionType : uint16_t {
|
||||
enum eConfigOptionType : uint8_t {
|
||||
CONFIG_OPTION_BOOL = 0,
|
||||
CONFIG_OPTION_INT = 1, /* e.g. 0/1/2*/
|
||||
CONFIG_OPTION_FLOAT = 2,
|
||||
@@ -96,7 +94,7 @@ enum eConfigOptionType : uint16_t {
|
||||
CONFIG_OPTION_VECTOR = 8,
|
||||
};
|
||||
|
||||
enum eConfigOptionFlags : uint32_t {
|
||||
enum eConfigOptionFlags : uint8_t {
|
||||
CONFIG_OPTION_FLAG_PERCENTAGE = (1 << 0),
|
||||
};
|
||||
|
||||
@@ -119,7 +117,7 @@ struct SConfigOptionDescription {
|
||||
};
|
||||
|
||||
struct SColorData {
|
||||
CColor color;
|
||||
CHyprColor color;
|
||||
};
|
||||
|
||||
struct SChoiceData {
|
||||
@@ -167,7 +165,7 @@ 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 PHLMONITOR);
|
||||
SWorkspaceRule getWorkspaceRuleFor(PHLWORKSPACE workspace);
|
||||
@@ -175,10 +173,10 @@ class CConfigManager {
|
||||
|
||||
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();
|
||||
|
||||
@@ -214,52 +212,58 @@ class CConfigManager {
|
||||
std::string getErrors();
|
||||
|
||||
// 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&);
|
||||
std::optional<std::string> handleWindowRule(const std::string&, const std::string&);
|
||||
std::optional<std::string> handleLayerRule(const std::string&, const std::string&);
|
||||
std::optional<std::string> handleWindowRuleV2(const std::string&, const std::string&);
|
||||
std::optional<std::string> handleWorkspaceRules(const std::string&, const std::string&);
|
||||
std::optional<std::string> handleBezier(const std::string&, const std::string&);
|
||||
std::optional<std::string> handleAnimation(const std::string&, const std::string&);
|
||||
std::optional<std::string> handleSource(const std::string&, const std::string&);
|
||||
std::optional<std::string> handleSubmap(const std::string&, const std::string&);
|
||||
std::optional<std::string> handleBlurLS(const std::string&, const std::string&);
|
||||
std::optional<std::string> handleBindWS(const std::string&, const std::string&);
|
||||
std::optional<std::string> handleEnv(const std::string&, const std::string&);
|
||||
std::optional<std::string> handlePlugin(const std::string&, const std::string&);
|
||||
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&);
|
||||
std::optional<std::string> handleWindowRule(const std::string&, const std::string&);
|
||||
std::optional<std::string> handleLayerRule(const std::string&, const std::string&);
|
||||
std::optional<std::string> handleWindowRuleV2(const std::string&, const std::string&);
|
||||
std::optional<std::string> handleWorkspaceRules(const std::string&, const std::string&);
|
||||
std::optional<std::string> handleBezier(const std::string&, const std::string&);
|
||||
std::optional<std::string> handleAnimation(const std::string&, const std::string&);
|
||||
std::optional<std::string> handleSource(const std::string&, const std::string&);
|
||||
std::optional<std::string> handleSubmap(const std::string&, const std::string&);
|
||||
std::optional<std::string> handleBlurLS(const std::string&, const std::string&);
|
||||
std::optional<std::string> handleBindWS(const std::string&, const std::string&);
|
||||
std::optional<std::string> handleEnv(const std::string&, const std::string&);
|
||||
std::optional<std::string> handlePlugin(const std::string&, const std::string&);
|
||||
|
||||
std::string configCurrentPath;
|
||||
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;
|
||||
@@ -269,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
|
||||
@@ -284,16 +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::deque<std::string> finalExecRequests;
|
||||
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.
|
||||
# #######################################################################################
|
||||
|
||||
@@ -149,13 +149,10 @@ animations {
|
||||
# Ref https://wiki.hyprland.org/Configuring/Workspace-Rules/
|
||||
# "Smart gaps" / "No gaps when only"
|
||||
# uncomment all if you wish to use that.
|
||||
# workspace = w[t1], gapsout:0, gapsin:0
|
||||
# workspace = w[tg1], gapsout:0, gapsin:0
|
||||
# workspace = w[tv1], gapsout:0, gapsin:0
|
||||
# workspace = f[1], gapsout:0, gapsin:0
|
||||
# windowrulev2 = bordersize 0, floating:0, onworkspace:w[t1]
|
||||
# windowrulev2 = rounding 0, floating:0, onworkspace:w[t1]
|
||||
# windowrulev2 = bordersize 0, floating:0, onworkspace:w[tg1]
|
||||
# windowrulev2 = rounding 0, floating:0, onworkspace:w[tg1]
|
||||
# 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]
|
||||
|
||||
|
@@ -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_IRUSR | S_IWUSR);
|
||||
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);
|
||||
};
|
@@ -1,10 +1,13 @@
|
||||
#include "HyprCtl.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <format>
|
||||
#include <fstream>
|
||||
#include <iterator>
|
||||
#include <netinet/in.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
@@ -36,6 +39,7 @@ using namespace Hyprutils::String;
|
||||
#include "debug/RollingLogFollow.hpp"
|
||||
#include "config/ConfigManager.hpp"
|
||||
#include "helpers/MiscFunctions.hpp"
|
||||
#include "../version.h"
|
||||
|
||||
static void trimTrailingComma(std::string& str) {
|
||||
if (!str.empty() && str.back() == ',')
|
||||
@@ -105,6 +109,7 @@ std::string CHyprCtl::getMonitorData(Hyprutils::Memory::CSharedPointer<CMonitor>
|
||||
"vrr": {},
|
||||
"solitary": "{:x}",
|
||||
"activelyTearing": {},
|
||||
"directScanoutTo": "{:x}",
|
||||
"disabled": {},
|
||||
"currentFormat": "{}",
|
||||
"mirrorOf": "{}",
|
||||
@@ -117,19 +122,20 @@ std::string CHyprCtl::getMonitorData(Hyprutils::Memory::CSharedPointer<CMonitor>
|
||||
escapeJSONStrings(m->activeSpecialWorkspace ? m->activeSpecialWorkspace->m_szName : ""), (int)m->vecReservedTopLeft.x, (int)m->vecReservedTopLeft.y,
|
||||
(int)m->vecReservedBottomRight.x, (int)m->vecReservedBottomRight.y, m->scale, (int)m->transform, (m == g_pCompositor->m_pLastMonitor ? "true" : "false"),
|
||||
(m->dpmsStatus ? "true" : "false"), (m->output->state->state().adaptiveSync ? "true" : "false"), (uint64_t)m->solitaryClient.get(),
|
||||
(m->tearingState.activelyTearing ? "true" : "false"), (m->m_bEnabled ? "false" : "true"), formatToString(m->output->state->state().drmFormat),
|
||||
m->pMirrorOf ? std::format("{}", m->pMirrorOf->ID) : "none", availableModesForOutput(m, format));
|
||||
(m->tearingState.activelyTearing ? "true" : "false"), (uint64_t)m->lastScanout.get(), (m->m_bEnabled ? "false" : "true"),
|
||||
formatToString(m->output->state->state().drmFormat), m->pMirrorOf ? std::format("{}", m->pMirrorOf->ID) : "none", availableModesForOutput(m, format));
|
||||
|
||||
} else {
|
||||
result += std::format("Monitor {} (ID {}):\n\t{}x{}@{:.5f} at {}x{}\n\tdescription: {}\n\tmake: {}\n\tmodel: {}\n\tserial: {}\n\tactive workspace: {} ({})\n\t"
|
||||
"special workspace: {} ({})\n\treserved: {} {} {} {}\n\tscale: {:.2f}\n\ttransform: {}\n\tfocused: {}\n\t"
|
||||
"dpmsStatus: {}\n\tvrr: {}\n\tsolitary: {:x}\n\tactivelyTearing: {}\n\tdisabled: {}\n\tcurrentFormat: {}\n\tmirrorOf: {}\n\tavailableModes: {}\n\n",
|
||||
"dpmsStatus: {}\n\tvrr: {}\n\tsolitary: {:x}\n\tactivelyTearing: {}\n\tdirectScanoutTo: {:x}\n\tdisabled: {}\n\tcurrentFormat: {}\n\tmirrorOf: "
|
||||
"{}\n\tavailableModes: {}\n\n",
|
||||
m->szName, m->ID, (int)m->vecPixelSize.x, (int)m->vecPixelSize.y, m->refreshRate, (int)m->vecPosition.x, (int)m->vecPosition.y, m->szShortDescription,
|
||||
m->output->make, m->output->model, m->output->serial, m->activeWorkspaceID(), (!m->activeWorkspace ? "" : m->activeWorkspace->m_szName),
|
||||
m->activeSpecialWorkspaceID(), (m->activeSpecialWorkspace ? m->activeSpecialWorkspace->m_szName : ""), (int)m->vecReservedTopLeft.x,
|
||||
(int)m->vecReservedTopLeft.y, (int)m->vecReservedBottomRight.x, (int)m->vecReservedBottomRight.y, m->scale, (int)m->transform,
|
||||
(m == g_pCompositor->m_pLastMonitor ? "yes" : "no"), (int)m->dpmsStatus, m->output->state->state().adaptiveSync, (uint64_t)m->solitaryClient.get(),
|
||||
m->tearingState.activelyTearing, !m->m_bEnabled, formatToString(m->output->state->state().drmFormat),
|
||||
m->tearingState.activelyTearing, (uint64_t)m->lastScanout.get(), !m->m_bEnabled, formatToString(m->output->state->state().drmFormat),
|
||||
m->pMirrorOf ? std::format("{}", m->pMirrorOf->ID) : "none", availableModesForOutput(m, format));
|
||||
}
|
||||
|
||||
@@ -239,7 +245,8 @@ std::string CHyprCtl::getWindowData(PHLWINDOW w, eHyprCtlOutputFormat format) {
|
||||
"grouped": [{}],
|
||||
"tags": [{}],
|
||||
"swallowing": "0x{:x}",
|
||||
"focusHistoryID": {}
|
||||
"focusHistoryID": {},
|
||||
"inhibitingIdle": {}
|
||||
}},)#",
|
||||
(uintptr_t)w.get(), (w->m_bIsMapped ? "true" : "false"), (w->isHidden() ? "true" : "false"), (int)w->m_vRealPosition.goal().x, (int)w->m_vRealPosition.goal().y,
|
||||
(int)w->m_vRealSize.goal().x, (int)w->m_vRealSize.goal().y, w->m_pWorkspace ? w->workspaceID() : WORKSPACE_INVALID,
|
||||
@@ -247,18 +254,18 @@ std::string CHyprCtl::getWindowData(PHLWINDOW w, eHyprCtlOutputFormat format) {
|
||||
(int64_t)w->monitorID(), escapeJSONStrings(w->m_szClass), escapeJSONStrings(w->m_szTitle), escapeJSONStrings(w->m_szInitialClass),
|
||||
escapeJSONStrings(w->m_szInitialTitle), w->getPID(), ((int)w->m_bIsX11 == 1 ? "true" : "false"), (w->m_bPinned ? "true" : "false"),
|
||||
(uint8_t)w->m_sFullscreenState.internal, (uint8_t)w->m_sFullscreenState.client, getGroupedData(w, format), getTagsData(w, format),
|
||||
(uintptr_t)w->m_pSwallowed.lock().get(), getFocusHistoryID(w));
|
||||
(uintptr_t)w->m_pSwallowed.lock().get(), getFocusHistoryID(w), (g_pInputManager->isWindowInhibiting(w, false) ? "true" : "false"));
|
||||
} else {
|
||||
return std::format(
|
||||
"Window {:x} -> {}:\n\tmapped: {}\n\thidden: {}\n\tat: {},{}\n\tsize: {},{}\n\tworkspace: {} ({})\n\tfloating: {}\n\tpseudo: {}\n\tmonitor: {}\n\tclass: {}\n\ttitle: "
|
||||
"{}\n\tinitialClass: {}\n\tinitialTitle: {}\n\tpid: "
|
||||
"{}\n\txwayland: {}\n\tpinned: "
|
||||
"{}\n\tfullscreen: {}\n\tfullscreenClient: {}\n\tgrouped: {}\n\ttags: {}\n\tswallowing: {:x}\n\tfocusHistoryID: {}\n\n",
|
||||
"{}\n\tfullscreen: {}\n\tfullscreenClient: {}\n\tgrouped: {}\n\ttags: {}\n\tswallowing: {:x}\n\tfocusHistoryID: {}\n\tinhibitingIdle: {}\n\n",
|
||||
(uintptr_t)w.get(), w->m_szTitle, (int)w->m_bIsMapped, (int)w->isHidden(), (int)w->m_vRealPosition.goal().x, (int)w->m_vRealPosition.goal().y,
|
||||
(int)w->m_vRealSize.goal().x, (int)w->m_vRealSize.goal().y, w->m_pWorkspace ? w->workspaceID() : WORKSPACE_INVALID, (!w->m_pWorkspace ? "" : w->m_pWorkspace->m_szName),
|
||||
(int)w->m_bIsFloating, (int)w->m_bIsPseudotiled, (int64_t)w->monitorID(), w->m_szClass, w->m_szTitle, w->m_szInitialClass, w->m_szInitialTitle, w->getPID(),
|
||||
(int)w->m_bIsX11, (int)w->m_bPinned, (uint8_t)w->m_sFullscreenState.internal, (uint8_t)w->m_sFullscreenState.client, getGroupedData(w, format), getTagsData(w, format),
|
||||
(uintptr_t)w->m_pSwallowed.lock().get(), getFocusHistoryID(w));
|
||||
(uintptr_t)w->m_pSwallowed.lock().get(), getFocusHistoryID(w), (int)g_pInputManager->isWindowInhibiting(w, false));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -303,12 +310,12 @@ std::string CHyprCtl::getWorkspaceData(PHLWORKSPACE w, eHyprCtlOutputFormat form
|
||||
"lastwindowtitle": "{}"
|
||||
}})#",
|
||||
w->m_iID, escapeJSONStrings(w->m_szName), escapeJSONStrings(PMONITOR ? PMONITOR->szName : "?"),
|
||||
escapeJSONStrings(PMONITOR ? std::to_string(PMONITOR->ID) : "null"), g_pCompositor->getWindowsOnWorkspace(w->m_iID),
|
||||
((int)w->m_bHasFullscreenWindow == 1 ? "true" : "false"), (uintptr_t)PLASTW.get(), PLASTW ? escapeJSONStrings(PLASTW->m_szTitle) : "");
|
||||
escapeJSONStrings(PMONITOR ? std::to_string(PMONITOR->ID) : "null"), w->getWindows(), ((int)w->m_bHasFullscreenWindow == 1 ? "true" : "false"),
|
||||
(uintptr_t)PLASTW.get(), PLASTW ? escapeJSONStrings(PLASTW->m_szTitle) : "");
|
||||
} else {
|
||||
return std::format("workspace ID {} ({}) on monitor {}:\n\tmonitorID: {}\n\twindows: {}\n\thasfullscreen: {}\n\tlastwindow: 0x{:x}\n\tlastwindowtitle: {}\n\n", w->m_iID,
|
||||
w->m_szName, PMONITOR ? PMONITOR->szName : "?", PMONITOR ? std::to_string(PMONITOR->ID) : "null", g_pCompositor->getWindowsOnWorkspace(w->m_iID),
|
||||
(int)w->m_bHasFullscreenWindow, (uintptr_t)PLASTW.get(), PLASTW ? PLASTW->m_szTitle : "");
|
||||
w->m_szName, PMONITOR ? PMONITOR->szName : "?", PMONITOR ? std::to_string(PMONITOR->ID) : "null", w->getWindows(), (int)w->m_bHasFullscreenWindow,
|
||||
(uintptr_t)PLASTW.get(), PLASTW ? PLASTW->m_szTitle : "");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -531,7 +538,7 @@ std::string configErrorsRequest(eHyprCtlOutputFormat format, std::string request
|
||||
CVarList errLines(currErrors, 0, '\n');
|
||||
if (format == eHyprCtlOutputFormat::FORMAT_JSON) {
|
||||
result += "[";
|
||||
for (auto line : errLines) {
|
||||
for (const auto& line : errLines) {
|
||||
result += std::format(
|
||||
R"#(
|
||||
"{}",)#",
|
||||
@@ -541,7 +548,7 @@ std::string configErrorsRequest(eHyprCtlOutputFormat format, std::string request
|
||||
trimTrailingComma(result);
|
||||
result += "\n]\n";
|
||||
} else {
|
||||
for (auto line : errLines) {
|
||||
for (const auto& line : errLines) {
|
||||
result += std::format("{}\n", line);
|
||||
}
|
||||
}
|
||||
@@ -811,28 +818,28 @@ std::string globalShortcutsRequest(eHyprCtlOutputFormat format, std::string requ
|
||||
std::string bindsRequest(eHyprCtlOutputFormat format, std::string request) {
|
||||
std::string ret = "";
|
||||
if (format == eHyprCtlOutputFormat::FORMAT_NORMAL) {
|
||||
for (auto const& kb : g_pKeybindManager->m_lKeybinds) {
|
||||
for (auto const& kb : g_pKeybindManager->m_vKeybinds) {
|
||||
ret += "bind";
|
||||
if (kb.locked)
|
||||
if (kb->locked)
|
||||
ret += "l";
|
||||
if (kb.mouse)
|
||||
if (kb->mouse)
|
||||
ret += "m";
|
||||
if (kb.release)
|
||||
if (kb->release)
|
||||
ret += "r";
|
||||
if (kb.repeat)
|
||||
if (kb->repeat)
|
||||
ret += "e";
|
||||
if (kb.nonConsuming)
|
||||
if (kb->nonConsuming)
|
||||
ret += "n";
|
||||
if (kb.hasDescription)
|
||||
if (kb->hasDescription)
|
||||
ret += "d";
|
||||
|
||||
ret += std::format("\n\tmodmask: {}\n\tsubmap: {}\n\tkey: {}\n\tkeycode: {}\n\tcatchall: {}\n\tdescription: {}\n\tdispatcher: {}\n\targ: {}\n\n", kb.modmask, kb.submap,
|
||||
kb.key, kb.keycode, kb.catchAll, kb.description, kb.handler, kb.arg);
|
||||
ret += std::format("\n\tmodmask: {}\n\tsubmap: {}\n\tkey: {}\n\tkeycode: {}\n\tcatchall: {}\n\tdescription: {}\n\tdispatcher: {}\n\targ: {}\n\n", kb->modmask,
|
||||
kb->submap, kb->key, kb->keycode, kb->catchAll, kb->description, kb->handler, kb->arg);
|
||||
}
|
||||
} else {
|
||||
// json
|
||||
ret += "[";
|
||||
for (auto const& kb : g_pKeybindManager->m_lKeybinds) {
|
||||
for (auto const& kb : g_pKeybindManager->m_vKeybinds) {
|
||||
ret += std::format(
|
||||
R"#(
|
||||
{{
|
||||
@@ -840,6 +847,7 @@ std::string bindsRequest(eHyprCtlOutputFormat format, std::string request) {
|
||||
"mouse": {},
|
||||
"release": {},
|
||||
"repeat": {},
|
||||
"longPress": {},
|
||||
"non_consuming": {},
|
||||
"has_description": {},
|
||||
"modmask": {},
|
||||
@@ -851,9 +859,9 @@ std::string bindsRequest(eHyprCtlOutputFormat format, std::string request) {
|
||||
"dispatcher": "{}",
|
||||
"arg": "{}"
|
||||
}},)#",
|
||||
kb.locked ? "true" : "false", kb.mouse ? "true" : "false", kb.release ? "true" : "false", kb.repeat ? "true" : "false", kb.nonConsuming ? "true" : "false",
|
||||
kb.hasDescription ? "true" : "false", kb.modmask, escapeJSONStrings(kb.submap), escapeJSONStrings(kb.key), kb.keycode, kb.catchAll ? "true" : "false",
|
||||
escapeJSONStrings(kb.description), escapeJSONStrings(kb.handler), escapeJSONStrings(kb.arg));
|
||||
kb->locked ? "true" : "false", kb->mouse ? "true" : "false", kb->release ? "true" : "false", kb->repeat ? "true" : "false", kb->longPress ? "true" : "false",
|
||||
kb->nonConsuming ? "true" : "false", kb->hasDescription ? "true" : "false", kb->modmask, escapeJSONStrings(kb->submap), escapeJSONStrings(kb->key), kb->keycode,
|
||||
kb->catchAll ? "true" : "false", escapeJSONStrings(kb->description), escapeJSONStrings(kb->handler), escapeJSONStrings(kb->arg));
|
||||
}
|
||||
trimTrailingComma(ret);
|
||||
ret += "]";
|
||||
@@ -871,8 +879,9 @@ std::string versionRequest(eHyprCtlOutputFormat format, std::string request) {
|
||||
std::string result = std::format("Hyprland {} built from branch {} at commit {} {} ({}).\n"
|
||||
"Date: {}\n"
|
||||
"Tag: {}, commits: {}\n"
|
||||
"built against aquamarine {}\n\n\n",
|
||||
HYPRLAND_VERSION, GIT_BRANCH, GIT_COMMIT_HASH, GIT_DIRTY, commitMsg, GIT_COMMIT_DATE, GIT_TAG, GIT_COMMITS, AQUAMARINE_VERSION);
|
||||
"built against:\n aquamarine {}\n hyprlang {}\n hyprutils {}\n hyprcursor {}\n hyprgraphics {}\n\n\n",
|
||||
HYPRLAND_VERSION, GIT_BRANCH, GIT_COMMIT_HASH, GIT_DIRTY, commitMsg, GIT_COMMIT_DATE, GIT_TAG, GIT_COMMITS, AQUAMARINE_VERSION,
|
||||
HYPRLANG_VERSION, HYPRUTILS_VERSION, HYPRCURSOR_VERSION, HYPRGRAPHICS_VERSION);
|
||||
|
||||
#if (!defined(LEGACY_RENDERER) && !defined(ISDEBUG) && !defined(NO_XWAYLAND))
|
||||
result += "no flags were set\n";
|
||||
@@ -901,9 +910,13 @@ std::string versionRequest(eHyprCtlOutputFormat format, std::string request) {
|
||||
"tag": "{}",
|
||||
"commits": "{}",
|
||||
"buildAquamarine": "{}",
|
||||
"buildHyprlang": "{}",
|
||||
"buildHyprutils": "{}",
|
||||
"buildHyprcursor": "{}",
|
||||
"buildHyprgraphics": "{}",
|
||||
"flags": [)#",
|
||||
GIT_BRANCH, GIT_COMMIT_HASH, HYPRLAND_VERSION, (strcmp(GIT_DIRTY, "dirty") == 0 ? "true" : "false"), escapeJSONStrings(commitMsg), GIT_COMMIT_DATE, GIT_TAG,
|
||||
GIT_COMMITS, AQUAMARINE_VERSION);
|
||||
GIT_COMMITS, AQUAMARINE_VERSION, HYPRLANG_VERSION, HYPRUTILS_VERSION, HYPRCURSOR_VERSION, HYPRGRAPHICS_VERSION);
|
||||
|
||||
#ifdef LEGACY_RENDERER
|
||||
result += "\"legacyrenderer\",";
|
||||
@@ -942,18 +955,51 @@ std::string systemInfoRequest(eHyprCtlOutputFormat format, std::string request)
|
||||
result += "\n\n";
|
||||
|
||||
#if defined(__DragonFly__) || defined(__FreeBSD__)
|
||||
const std::string GPUINFO = execAndGet("pciconf -lv | fgrep -A4 vga");
|
||||
const std::string GPUINFO = execAndGet("pciconf -lv | grep -F -A4 vga");
|
||||
#elif defined(__arm__) || defined(__aarch64__)
|
||||
const std::string GPUINFO = execAndGet("cat /proc/device-tree/soc*/gpu*/compatible");
|
||||
std::string GPUINFO;
|
||||
const std::filesystem::path dev_tree = "/proc/device-tree";
|
||||
try {
|
||||
if (std::filesystem::exists(dev_tree) && std::filesystem::is_directory(dev_tree)) {
|
||||
std::for_each(std::filesystem::directory_iterator(dev_tree), std::filesystem::directory_iterator{}, [&](const std::filesystem::directory_entry& entry) {
|
||||
if (std::filesystem::is_directory(entry) && entry.path().filename().string().starts_with("soc")) {
|
||||
std::for_each(std::filesystem::directory_iterator(entry.path()), std::filesystem::directory_iterator{}, [&](const std::filesystem::directory_entry& sub_entry) {
|
||||
if (std::filesystem::is_directory(sub_entry) && sub_entry.path().filename().string().starts_with("gpu")) {
|
||||
std::filesystem::path file_path = sub_entry.path() / "compatible";
|
||||
std::ifstream file(file_path);
|
||||
if (file)
|
||||
GPUINFO.append(std::istreambuf_iterator<char>(file), std::istreambuf_iterator<char>());
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
} catch (...) { GPUINFO = "error"; }
|
||||
#else
|
||||
const std::string GPUINFO = execAndGet("lspci -vnn | grep VGA");
|
||||
#endif
|
||||
result += "GPU information: \n" + GPUINFO;
|
||||
if (GPUINFO.contains("NVIDIA") && std::filesystem::exists("/proc/driver/nvidia/version"))
|
||||
result += execAndGet("cat /proc/driver/nvidia/version | grep NVRM");
|
||||
if (GPUINFO.contains("NVIDIA") && std::filesystem::exists("/proc/driver/nvidia/version")) {
|
||||
std::ifstream file("/proc/driver/nvidia/version");
|
||||
std::string line;
|
||||
if (file.is_open()) {
|
||||
while (std::getline(file, line)) {
|
||||
if (!line.contains("NVRM"))
|
||||
continue;
|
||||
result += line;
|
||||
result += "\n";
|
||||
}
|
||||
} else
|
||||
result += "error";
|
||||
}
|
||||
result += "\n\n";
|
||||
|
||||
result += "os-release: " + execAndGet("cat /etc/os-release") + "\n\n";
|
||||
if (std::ifstream file("/etc/os-release"); file.is_open()) {
|
||||
std::stringstream buffer;
|
||||
buffer << file.rdbuf();
|
||||
result += "os-release: " + buffer.str() + "\n\n";
|
||||
} else
|
||||
result += "os-release: error\n\n";
|
||||
|
||||
result += "plugins:\n";
|
||||
if (g_pPluginSystem) {
|
||||
@@ -1249,7 +1295,7 @@ std::string dispatchSeterror(eHyprCtlOutputFormat format, std::string request) {
|
||||
return "ok";
|
||||
}
|
||||
|
||||
const CColor COLOR = configStringToInt(vars[1]);
|
||||
const CHyprColor COLOR = configStringToInt(vars[1]).value_or(0);
|
||||
|
||||
for (size_t i = 2; i < vars.size(); ++i)
|
||||
errorMessage += vars[i] + ' ';
|
||||
@@ -1310,17 +1356,16 @@ std::string dispatchGetOption(eHyprCtlOutputFormat format, std::string request)
|
||||
return std::format("custom type: {}\nset: {}", ((ICustomConfigValueData*)std::any_cast<void*>(VAL))->toString(), VAR->m_bSetByUser);
|
||||
} else {
|
||||
if (TYPE == typeid(Hyprlang::INT))
|
||||
return std::format("{{\"option\": \"{}\", \"int\": {}, \"set\": {} }}", curitem, std::any_cast<Hyprlang::INT>(VAL), VAR->m_bSetByUser);
|
||||
return std::format(R"({{"option": "{}", "int": {}, "set": {} }})", curitem, std::any_cast<Hyprlang::INT>(VAL), VAR->m_bSetByUser);
|
||||
else if (TYPE == typeid(Hyprlang::FLOAT))
|
||||
return std::format("{{\"option\": \"{}\", \"float\": {:2f}, \"set\": {} }}", curitem, std::any_cast<Hyprlang::FLOAT>(VAL), VAR->m_bSetByUser);
|
||||
return std::format(R"({{"option": "{}", "float": {:2f}, "set": {} }})", curitem, std::any_cast<Hyprlang::FLOAT>(VAL), VAR->m_bSetByUser);
|
||||
else if (TYPE == typeid(Hyprlang::VEC2))
|
||||
return std::format("{{\"option\": \"{}\", \"vec2\": [{},{}], \"set\": {} }}", curitem, std::any_cast<Hyprlang::VEC2>(VAL).x, std::any_cast<Hyprlang::VEC2>(VAL).y,
|
||||
return std::format(R"({{"option": "{}", "vec2": [{},{}], "set": {} }})", curitem, std::any_cast<Hyprlang::VEC2>(VAL).x, std::any_cast<Hyprlang::VEC2>(VAL).y,
|
||||
VAR->m_bSetByUser);
|
||||
else if (TYPE == typeid(Hyprlang::STRING))
|
||||
return std::format("{{\"option\": \"{}\", \"str\": \"{}\", \"set\": {} }}", curitem, escapeJSONStrings(std::any_cast<Hyprlang::STRING>(VAL)), VAR->m_bSetByUser);
|
||||
return std::format(R"({{"option": "{}", "str": "{}", "set": {} }})", curitem, escapeJSONStrings(std::any_cast<Hyprlang::STRING>(VAL)), VAR->m_bSetByUser);
|
||||
else if (TYPE == typeid(void*))
|
||||
return std::format("{{\"option\": \"{}\", \"custom\": \"{}\", \"set\": {} }}", curitem, ((ICustomConfigValueData*)std::any_cast<void*>(VAL))->toString(),
|
||||
VAR->m_bSetByUser);
|
||||
return std::format(R"({{"option": "{}", "custom": "{}", "set": {} }})", curitem, ((ICustomConfigValueData*)std::any_cast<void*>(VAL))->toString(), VAR->m_bSetByUser);
|
||||
}
|
||||
|
||||
return "invalid type (internal error)";
|
||||
@@ -1435,17 +1480,40 @@ std::string dispatchPlugin(eHyprCtlOutputFormat format, std::string request) {
|
||||
|
||||
g_pPluginSystem->unloadPlugin(PLUGIN);
|
||||
} else if (OPERATION == "list") {
|
||||
const auto PLUGINS = g_pPluginSystem->getAllPlugins();
|
||||
const auto PLUGINS = g_pPluginSystem->getAllPlugins();
|
||||
std::string result = "";
|
||||
|
||||
if (PLUGINS.size() == 0)
|
||||
return "no plugins loaded";
|
||||
if (format == eHyprCtlOutputFormat::FORMAT_JSON) {
|
||||
result += "[";
|
||||
|
||||
std::string list = "";
|
||||
for (auto const& p : PLUGINS) {
|
||||
list += std::format("\nPlugin {} by {}:\n\tHandle: {:x}\n\tVersion: {}\n\tDescription: {}\n", p->name, p->author, (uintptr_t)p->m_pHandle, p->version, p->description);
|
||||
if (PLUGINS.size() == 0)
|
||||
return "[]";
|
||||
|
||||
for (auto const& p : PLUGINS) {
|
||||
result += std::format(
|
||||
R"#(
|
||||
{{
|
||||
"name": "{}",
|
||||
"author": "{}",
|
||||
"handle": "{:x}",
|
||||
"version": "{}",
|
||||
"description": "{}"
|
||||
}},)#",
|
||||
escapeJSONStrings(p->name), escapeJSONStrings(p->author), (uintptr_t)p->m_pHandle, escapeJSONStrings(p->version), escapeJSONStrings(p->description));
|
||||
}
|
||||
trimTrailingComma(result);
|
||||
result += "]";
|
||||
} else {
|
||||
if (PLUGINS.size() == 0)
|
||||
return "no plugins loaded";
|
||||
|
||||
for (auto const& p : PLUGINS) {
|
||||
result +=
|
||||
std::format("\nPlugin {} by {}:\n\tHandle: {:x}\n\tVersion: {}\n\tDescription: {}\n", p->name, p->author, (uintptr_t)p->m_pHandle, p->version, p->description);
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
return result;
|
||||
} else {
|
||||
return "unknown opt";
|
||||
}
|
||||
@@ -1469,9 +1537,8 @@ std::string dispatchNotify(eHyprCtlOutputFormat format, std::string request) {
|
||||
icon = std::stoi(ICON);
|
||||
} catch (std::exception& e) { return "invalid arg 1"; }
|
||||
|
||||
if (icon > ICON_NONE || icon < 0) {
|
||||
if (icon > ICON_NONE || icon < 0)
|
||||
icon = ICON_NONE;
|
||||
}
|
||||
|
||||
const auto TIME = vars[2];
|
||||
int time = 0;
|
||||
@@ -1479,10 +1546,13 @@ std::string dispatchNotify(eHyprCtlOutputFormat format, std::string request) {
|
||||
time = std::stoi(TIME);
|
||||
} catch (std::exception& e) { return "invalid arg 2"; }
|
||||
|
||||
CColor color = configStringToInt(vars[3]);
|
||||
const auto COLOR_RESULT = configStringToInt(vars[3]);
|
||||
if (!COLOR_RESULT)
|
||||
return "invalid arg 3";
|
||||
CHyprColor color = *COLOR_RESULT;
|
||||
|
||||
size_t msgidx = 4;
|
||||
float fontsize = 13.f;
|
||||
size_t msgidx = 4;
|
||||
float fontsize = 13.f;
|
||||
if (vars[msgidx].length() > 9 && vars[msgidx].compare(0, 9, "fontsize:") == 0) {
|
||||
const auto FONTSIZE = vars[msgidx].substr(9);
|
||||
|
||||
@@ -1702,7 +1772,7 @@ std::string CHyprCtl::getReply(std::string request) {
|
||||
}
|
||||
|
||||
for (auto const& w : g_pCompositor->m_vWindows) {
|
||||
if (!w->m_bIsMapped || !g_pCompositor->isWorkspaceVisible(w->m_pWorkspace))
|
||||
if (!w->m_bIsMapped || !w->m_pWorkspace || !w->m_pWorkspace->isVisible())
|
||||
continue;
|
||||
|
||||
w->updateDynamicRules();
|
||||
@@ -1740,13 +1810,13 @@ void runWritingDebugLogThread(const int conn) {
|
||||
Debug::log(LOG, "In followlog thread, got connection, start writing: {}", conn);
|
||||
//will be finished, when reading side close connection
|
||||
std::thread([conn]() {
|
||||
while (Debug::RollingLogFollow::Get().IsRunning()) {
|
||||
if (Debug::RollingLogFollow::Get().isEmpty(conn)) {
|
||||
while (Debug::SRollingLogFollow::get().isRunning()) {
|
||||
if (Debug::SRollingLogFollow::get().isEmpty(conn)) {
|
||||
std::this_thread::sleep_for(1000ms);
|
||||
continue;
|
||||
}
|
||||
|
||||
auto line = Debug::RollingLogFollow::Get().GetLog(conn);
|
||||
auto line = Debug::SRollingLogFollow::get().getLog(conn);
|
||||
if (!successWrite(conn, line))
|
||||
// We cannot write, when connection is closed. So thread will successfully exit by itself
|
||||
break;
|
||||
@@ -1754,7 +1824,7 @@ void runWritingDebugLogThread(const int conn) {
|
||||
std::this_thread::sleep_for(100ms);
|
||||
}
|
||||
close(conn);
|
||||
Debug::RollingLogFollow::Get().StopFor(conn);
|
||||
Debug::SRollingLogFollow::get().stopFor(conn);
|
||||
}).detach();
|
||||
}
|
||||
|
||||
@@ -1813,9 +1883,9 @@ int hyprCtlFDTick(int fd, uint32_t mask, void* data) {
|
||||
|
||||
if (isFollowUpRollingLogRequest(request)) {
|
||||
Debug::log(LOG, "Followup rollinglog request received. Starting thread to write to socket.");
|
||||
Debug::RollingLogFollow::Get().StartFor(ACCEPTEDCONNECTION);
|
||||
Debug::SRollingLogFollow::get().startFor(ACCEPTEDCONNECTION);
|
||||
runWritingDebugLogThread(ACCEPTEDCONNECTION);
|
||||
Debug::log(LOG, Debug::RollingLogFollow::Get().DebugInfo());
|
||||
Debug::log(LOG, Debug::SRollingLogFollow::get().debugInfo());
|
||||
} else
|
||||
close(ACCEPTEDCONNECTION);
|
||||
|
||||
|
@@ -8,7 +8,12 @@ CHyprDebugOverlay::CHyprDebugOverlay() {
|
||||
}
|
||||
|
||||
void CHyprMonitorDebugOverlay::renderData(PHLMONITOR pMonitor, float durationUs) {
|
||||
m_dLastRenderTimes.push_back(durationUs / 1000.f);
|
||||
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();
|
||||
@@ -18,7 +23,12 @@ void CHyprMonitorDebugOverlay::renderData(PHLMONITOR pMonitor, float durationUs)
|
||||
}
|
||||
|
||||
void CHyprMonitorDebugOverlay::renderDataNoOverlay(PHLMONITOR pMonitor, float durationUs) {
|
||||
m_dLastRenderTimesNoOverlay.push_back(durationUs / 1000.f);
|
||||
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();
|
||||
@@ -28,7 +38,12 @@ void CHyprMonitorDebugOverlay::renderDataNoOverlay(PHLMONITOR pMonitor, float du
|
||||
}
|
||||
|
||||
void CHyprMonitorDebugOverlay::frameData(PHLMONITOR pMonitor) {
|
||||
m_dLastFrametimes.push_back(std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now() - m_tpLastFrame).count() / 1000.f);
|
||||
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();
|
||||
@@ -189,14 +204,29 @@ int CHyprMonitorDebugOverlay::draw(int offset) {
|
||||
}
|
||||
|
||||
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(PHLMONITOR pMonitor, float durationUs) {
|
||||
static auto PDEBUGOVERLAY = CConfigValue<Hyprlang::INT>("debug:overlay");
|
||||
|
||||
if (!*PDEBUGOVERLAY)
|
||||
return;
|
||||
|
||||
m_mMonitorOverlays[pMonitor].renderDataNoOverlay(pMonitor, durationUs);
|
||||
}
|
||||
|
||||
void CHyprDebugOverlay::frameData(PHLMONITOR pMonitor) {
|
||||
static auto PDEBUGOVERLAY = CConfigValue<Hyprlang::INT>("debug:overlay");
|
||||
|
||||
if (!*PDEBUGOVERLAY)
|
||||
return;
|
||||
|
||||
m_mMonitorOverlays[pMonitor].frameData(pMonitor);
|
||||
}
|
||||
|
||||
|
@@ -3,9 +3,9 @@
|
||||
#include "../defines.hpp"
|
||||
#include "../helpers/Monitor.hpp"
|
||||
#include "../render/Texture.hpp"
|
||||
#include <deque>
|
||||
#include <cairo/cairo.h>
|
||||
#include <map>
|
||||
#include <deque>
|
||||
|
||||
class CHyprRenderer;
|
||||
|
||||
|
@@ -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,11 +34,11 @@ 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 = icon != eIcons::ICON_NONE ? " " + text /* tiny bit of padding otherwise icon touches text */ : text;
|
||||
PNOTIF->color = color == CColor(0) ? ICONS_COLORS[icon] : color;
|
||||
PNOTIF->color = color == CHyprColor(0) ? ICONS_COLORS[icon] : color;
|
||||
PNOTIF->started.reset();
|
||||
PNOTIF->timeMs = timeMs;
|
||||
PNOTIF->icon = icon;
|
||||
@@ -51,12 +51,12 @@ void CHyprNotificationOverlay::addNotification(const std::string& text, const CC
|
||||
|
||||
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());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -87,7 +87,7 @@ CBox CHyprNotificationOverlay::drawNotifications(PHLMONITOR pMonitor) {
|
||||
const auto iconBackendID = iconBackendFromLayout(layout);
|
||||
const auto PBEZIER = g_pAnimationManager->getBezier("default");
|
||||
|
||||
for (auto const& 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,7 +182,7 @@ CBox CHyprNotificationOverlay::drawNotifications(PHLMONITOR 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};
|
||||
}
|
||||
@@ -205,7 +205,7 @@ void CHyprNotificationOverlay::draw(PHLMONITOR 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(PHLMONITOR 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;
|
||||
@@ -42,23 +42,23 @@ class CHyprNotificationOverlay {
|
||||
~CHyprNotificationOverlay();
|
||||
|
||||
void draw(PHLMONITOR pMonitor);
|
||||
void addNotification(const std::string& text, const CColor& color, const float timeMs, const eIcons icon = ICON_NONE, const float fontSize = 13.f);
|
||||
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(PHLMONITOR pMonitor);
|
||||
CBox m_bLastDamage;
|
||||
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;
|
||||
cairo_surface_t* m_pCairoSurface = nullptr;
|
||||
cairo_t* m_pCairo = nullptr;
|
||||
|
||||
PHLMONITORREF m_pLastMonitor;
|
||||
Vector2D m_vecLastSize = Vector2D(-1, -1);
|
||||
PHLMONITORREF m_pLastMonitor;
|
||||
Vector2D m_vecLastSize = Vector2D(-1, -1);
|
||||
|
||||
SP<CTexture> m_pTexture;
|
||||
SP<CTexture> m_pTexture;
|
||||
};
|
||||
|
||||
inline std::unique_ptr<CHyprNotificationOverlay> g_pHyprNotificationOverlay;
|
||||
|
@@ -18,7 +18,7 @@ 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;
|
||||
|
||||
@@ -26,6 +26,7 @@ void Debug::log(LogLevel level, std::string str) {
|
||||
return;
|
||||
|
||||
std::string coloredStr = str;
|
||||
//NOLINTBEGIN
|
||||
switch (level) {
|
||||
case LOG:
|
||||
str = "[LOG] " + str;
|
||||
@@ -53,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
|
||||
|
@@ -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)
|
||||
|
@@ -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;
|
||||
|
37
src/desktop/LayerRule.cpp
Normal file
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
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));
|
||||
|
||||
auto 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);
|
||||
|
||||
@@ -378,38 +378,57 @@ void CLayerSurface::applyRules() {
|
||||
animationStyle.reset();
|
||||
|
||||
for (auto const& rule : g_pConfigManager->getMatchingRules(self.lock())) {
|
||||
if (rule.rule == "noanim")
|
||||
noAnimations = true;
|
||||
else if (rule.rule == "blur")
|
||||
forceBlur = true;
|
||||
else if (rule.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(' ');
|
||||
std::string alphaValue = "";
|
||||
if (FIRST_SPACE_POS != std::string::npos)
|
||||
alphaValue = rule.rule.substr(FIRST_SPACE_POS + 1);
|
||||
switch (rule->ruleType) {
|
||||
case CLayerRule::RULE_NOANIM: {
|
||||
noAnimations = true;
|
||||
break;
|
||||
}
|
||||
case CLayerRule::RULE_BLUR: {
|
||||
forceBlur = true;
|
||||
break;
|
||||
}
|
||||
case CLayerRule::RULE_BLURPOPUPS: {
|
||||
forceBlurPopups = true;
|
||||
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);
|
||||
|
||||
try {
|
||||
ignoreAlpha = true;
|
||||
if (!alphaValue.empty())
|
||||
ignoreAlphaValue = std::stof(alphaValue);
|
||||
} catch (...) { Debug::log(ERR, "Invalid value passed to ignoreAlpha"); }
|
||||
} else if (rule.rule == "dimaround") {
|
||||
dimAround = true;
|
||||
} else if (rule.rule.starts_with("xray")) {
|
||||
CVarList vars{rule.rule, 0, ' '};
|
||||
try {
|
||||
xray = configStringToInt(vars[1]);
|
||||
} catch (...) {}
|
||||
} else if (rule.rule.starts_with("animation")) {
|
||||
CVarList vars{rule.rule, 2, 's'};
|
||||
animationStyle = vars[1];
|
||||
} else if (rule.rule.starts_with("order")) {
|
||||
CVarList vars{rule.rule, 2, 's'};
|
||||
try {
|
||||
order = std::stoi(vars[1]);
|
||||
} catch (...) { Debug::log(ERR, "Invalid value passed to order"); }
|
||||
try {
|
||||
ignoreAlpha = true;
|
||||
if (!alphaValue.empty())
|
||||
ignoreAlphaValue = std::stof(alphaValue);
|
||||
} catch (...) { Debug::log(ERR, "Invalid value passed to ignoreAlpha"); }
|
||||
break;
|
||||
}
|
||||
case CLayerRule::RULE_DIMAROUND: {
|
||||
dimAround = true;
|
||||
break;
|
||||
}
|
||||
case CLayerRule::RULE_XRAY: {
|
||||
CVarList vars{rule->rule, 0, ' '};
|
||||
try {
|
||||
xray = configStringToInt(vars[1]).value_or(false);
|
||||
} catch (...) {}
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -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;
|
||||
|
||||
|
@@ -16,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();
|
||||
|
||||
|
@@ -41,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,8 +58,7 @@ class CPopup {
|
||||
|
||||
bool m_bRequestedReposition = false;
|
||||
|
||||
bool m_bInert = false;
|
||||
bool m_bMapped = false;
|
||||
bool m_bInert = false;
|
||||
|
||||
//
|
||||
std::vector<SP<CPopup>> m_vChildren;
|
||||
|
@@ -1,3 +1,5 @@
|
||||
#include <re2/re2.h>
|
||||
|
||||
#include <any>
|
||||
#include <bit>
|
||||
#include <string_view>
|
||||
@@ -413,12 +415,12 @@ void CWindow::moveToWorkspace(PHLWORKSPACE pWorkspace) {
|
||||
|
||||
setAnimationsToMove();
|
||||
|
||||
g_pCompositor->updateWorkspaceWindows(OLDWORKSPACE->m_iID);
|
||||
g_pCompositor->updateWorkspaceWindowData(OLDWORKSPACE->m_iID);
|
||||
OLDWORKSPACE->updateWindows();
|
||||
OLDWORKSPACE->updateWindowData();
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(OLDWORKSPACE->monitorID());
|
||||
|
||||
g_pCompositor->updateWorkspaceWindows(workspaceID());
|
||||
g_pCompositor->updateWorkspaceWindowData(workspaceID());
|
||||
pWorkspace->updateWindows();
|
||||
pWorkspace->updateWindowData();
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(monitorID());
|
||||
|
||||
g_pCompositor->updateAllWindowsAnimatedDecorationValues();
|
||||
@@ -437,13 +439,13 @@ void CWindow::moveToWorkspace(PHLWORKSPACE pWorkspace) {
|
||||
// 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 (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;
|
||||
|
||||
@@ -516,7 +518,7 @@ void CWindow::onUnmap() {
|
||||
|
||||
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()) {
|
||||
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);
|
||||
@@ -527,8 +529,10 @@ void CWindow::onUnmap() {
|
||||
if (PMONITOR && PMONITOR->solitaryClient.lock().get() == this)
|
||||
PMONITOR->solitaryClient.reset();
|
||||
|
||||
g_pCompositor->updateWorkspaceWindows(workspaceID());
|
||||
g_pCompositor->updateWorkspaceWindowData(workspaceID());
|
||||
if (m_pWorkspace) {
|
||||
m_pWorkspace->updateWindows();
|
||||
m_pWorkspace->updateWindowData();
|
||||
}
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(monitorID());
|
||||
g_pCompositor->updateAllWindowsAnimatedDecorationValues();
|
||||
|
||||
@@ -612,154 +616,179 @@ 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;
|
||||
|
||||
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")) {
|
||||
try {
|
||||
CVarList vars(r.szRule, 0, ' ');
|
||||
switch (r->ruleType) {
|
||||
case CWindowRule::RULE_TAG: {
|
||||
CVarList vars{r->szRule, 0, 's', true};
|
||||
|
||||
int opacityIDX = 0;
|
||||
|
||||
for (auto const& r : vars) {
|
||||
if (r == "opacity")
|
||||
continue;
|
||||
|
||||
if (r == "override") {
|
||||
if (opacityIDX == 1)
|
||||
m_sWindowData.alpha = CWindowOverridableVar(SAlphaValue{m_sWindowData.alpha.value().m_fAlpha, true}, priority);
|
||||
else if (opacityIDX == 2)
|
||||
m_sWindowData.alphaInactive = CWindowOverridableVar(SAlphaValue{m_sWindowData.alphaInactive.value().m_fAlpha, true}, priority);
|
||||
else if (opacityIDX == 3)
|
||||
m_sWindowData.alphaFullscreen = CWindowOverridableVar(SAlphaValue{m_sWindowData.alphaFullscreen.value().m_fAlpha, true}, priority);
|
||||
} else {
|
||||
if (opacityIDX == 0) {
|
||||
m_sWindowData.alpha = CWindowOverridableVar(SAlphaValue{std::stof(r), false}, priority);
|
||||
} else if (opacityIDX == 1) {
|
||||
m_sWindowData.alphaInactive = CWindowOverridableVar(SAlphaValue{std::stof(r), false}, priority);
|
||||
} else if (opacityIDX == 2) {
|
||||
m_sWindowData.alphaFullscreen = CWindowOverridableVar(SAlphaValue{std::stof(r), false}, priority);
|
||||
} else {
|
||||
throw std::runtime_error("more than 3 alpha values");
|
||||
}
|
||||
|
||||
opacityIDX++;
|
||||
}
|
||||
}
|
||||
|
||||
if (opacityIDX == 1) {
|
||||
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);
|
||||
m_sWindowData.animationStyle = CWindowOverridableVar(STYLE, priority);
|
||||
} else if (r.szRule.starts_with("bordercolor")) {
|
||||
try {
|
||||
// Each vector will only get used if it has at least one color
|
||||
CGradientValueData activeBorderGradient = {};
|
||||
CGradientValueData inactiveBorderGradient = {};
|
||||
bool active = true;
|
||||
CVarList colorsAndAngles = CVarList(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);
|
||||
return;
|
||||
}
|
||||
|
||||
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);
|
||||
active = false;
|
||||
} 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));
|
||||
else
|
||||
inactiveBorderGradient.m_vColors.push_back(configStringToInt(token));
|
||||
}
|
||||
|
||||
// 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);
|
||||
else if (activeBorderGradient.m_vColors.empty())
|
||||
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 (...) {}
|
||||
if (vars.size() == 2 && vars[0] == "tag")
|
||||
m_tags.applyTag(vars[1], true);
|
||||
else
|
||||
Debug::log(ERR, "Tag rule invalid: {}", r->szRule);
|
||||
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_OPACITY: {
|
||||
try {
|
||||
CVarList vars(r->szRule, 0, ' ');
|
||||
|
||||
if (IDLERULE == "none")
|
||||
m_eIdleInhibitMode = IDLEINHIBIT_NONE;
|
||||
else if (IDLERULE == "always")
|
||||
m_eIdleInhibitMode = IDLEINHIBIT_ALWAYS;
|
||||
else if (IDLERULE == "focus")
|
||||
m_eIdleInhibitMode = IDLEINHIBIT_FOCUS;
|
||||
else if (IDLERULE == "fullscreen")
|
||||
m_eIdleInhibitMode = IDLEINHIBIT_FULLSCREEN;
|
||||
else
|
||||
Debug::log(ERR, "Rule idleinhibit: unknown mode {}", IDLERULE);
|
||||
} else if (r.szRule.starts_with("maxsize")) {
|
||||
try {
|
||||
if (!m_bIsFloating)
|
||||
return;
|
||||
const auto VEC = configStringToVector2D(r.szRule.substr(8));
|
||||
if (VEC.x < 1 || VEC.y < 1) {
|
||||
Debug::log(ERR, "Invalid size for maxsize");
|
||||
return;
|
||||
int opacityIDX = 0;
|
||||
|
||||
for (auto const& r : vars) {
|
||||
if (r == "opacity")
|
||||
continue;
|
||||
|
||||
if (r == "override") {
|
||||
if (opacityIDX == 1)
|
||||
m_sWindowData.alpha = CWindowOverridableVar(SAlphaValue{m_sWindowData.alpha.value().m_fAlpha, true}, priority);
|
||||
else if (opacityIDX == 2)
|
||||
m_sWindowData.alphaInactive = CWindowOverridableVar(SAlphaValue{m_sWindowData.alphaInactive.value().m_fAlpha, true}, priority);
|
||||
else if (opacityIDX == 3)
|
||||
m_sWindowData.alphaFullscreen = CWindowOverridableVar(SAlphaValue{m_sWindowData.alphaFullscreen.value().m_fAlpha, true}, priority);
|
||||
} else {
|
||||
if (opacityIDX == 0) {
|
||||
m_sWindowData.alpha = CWindowOverridableVar(SAlphaValue{std::stof(r), false}, priority);
|
||||
} else if (opacityIDX == 1) {
|
||||
m_sWindowData.alphaInactive = CWindowOverridableVar(SAlphaValue{std::stof(r), false}, priority);
|
||||
} else if (opacityIDX == 2) {
|
||||
m_sWindowData.alphaFullscreen = CWindowOverridableVar(SAlphaValue{std::stof(r), false}, priority);
|
||||
} else {
|
||||
throw std::runtime_error("more than 3 alpha values");
|
||||
}
|
||||
|
||||
opacityIDX++;
|
||||
}
|
||||
}
|
||||
|
||||
if (opacityIDX == 1) {
|
||||
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()); }
|
||||
break;
|
||||
}
|
||||
case CWindowRule::RULE_ANIMATION: {
|
||||
auto STYLE = r->szRule.substr(r->szRule.find_first_of(' ') + 1);
|
||||
m_sWindowData.animationStyle = CWindowOverridableVar(STYLE, priority);
|
||||
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);
|
||||
|
||||
// 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(CHyprColor(configStringToInt(colorsAndAngles[0]).value_or(0))), priority);
|
||||
m_sWindowData.inactiveBorderColor = CWindowOverridableVar(CGradientValueData(CHyprColor(configStringToInt(colorsAndAngles[1]).value_or(0))), priority);
|
||||
return;
|
||||
}
|
||||
|
||||
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);
|
||||
active = false;
|
||||
} 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).value_or(0));
|
||||
else
|
||||
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);
|
||||
else if (activeBorderGradient.m_vColors.empty())
|
||||
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()); }
|
||||
break;
|
||||
}
|
||||
case CWindowRule::RULE_IDLEINHIBIT: {
|
||||
auto IDLERULE = r->szRule.substr(r->szRule.find_first_of(' ') + 1);
|
||||
|
||||
if (IDLERULE == "none")
|
||||
m_eIdleInhibitMode = IDLEINHIBIT_NONE;
|
||||
else if (IDLERULE == "always")
|
||||
m_eIdleInhibitMode = IDLEINHIBIT_ALWAYS;
|
||||
else if (IDLERULE == "focus")
|
||||
m_eIdleInhibitMode = IDLEINHIBIT_FOCUS;
|
||||
else if (IDLERULE == "fullscreen")
|
||||
m_eIdleInhibitMode = IDLEINHIBIT_FULLSCREEN;
|
||||
else
|
||||
Debug::log(ERR, "Rule idleinhibit: unknown mode {}", IDLERULE);
|
||||
break;
|
||||
}
|
||||
case CWindowRule::RULE_MAXSIZE: {
|
||||
try {
|
||||
if (!m_bIsFloating)
|
||||
return;
|
||||
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);
|
||||
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));
|
||||
if (VEC.x < 1 || VEC.y < 1) {
|
||||
Debug::log(ERR, "Invalid size for minsize");
|
||||
return;
|
||||
}
|
||||
|
||||
m_sWindowData.minSize = CWindowOverridableVar(VEC, priority);
|
||||
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()); }
|
||||
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()); }
|
||||
}
|
||||
|
||||
m_sWindowData.maxSize = CWindowOverridableVar(VEC, priority);
|
||||
clampWindowSize(std::nullopt, m_sWindowData.maxSize.value());
|
||||
|
||||
} catch (std::exception& e) { Debug::log(ERR, "maxsize rule \"{}\" failed with: {}", r.szRule, e.what()); }
|
||||
} else if (r.szRule.starts_with("minsize")) {
|
||||
try {
|
||||
if (!m_bIsFloating)
|
||||
return;
|
||||
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);
|
||||
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()); }
|
||||
} else if (r.szRule == "renderunfocused") {
|
||||
m_sWindowData.renderUnfocused = CWindowOverridableVar(true, priority);
|
||||
g_pHyprRenderer->addWindowToRenderUnfocused(m_pSelf.lock());
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -784,7 +813,7 @@ void CWindow::updateDynamicRules() {
|
||||
m_tags.removeDynamicTags();
|
||||
|
||||
m_vMatchedRules = g_pConfigManager->getMatchingRules(m_pSelf.lock());
|
||||
for (auto const& r : m_vMatchedRules) {
|
||||
for (const auto& r : m_vMatchedRules) {
|
||||
applyDynamicRule(r);
|
||||
}
|
||||
|
||||
@@ -855,8 +884,10 @@ void CWindow::createGroup() {
|
||||
|
||||
addWindowDeco(std::make_unique<CHyprGroupBarDecoration>(m_pSelf.lock()));
|
||||
|
||||
g_pCompositor->updateWorkspaceWindows(workspaceID());
|
||||
g_pCompositor->updateWorkspaceWindowData(workspaceID());
|
||||
if (m_pWorkspace) {
|
||||
m_pWorkspace->updateWindows();
|
||||
m_pWorkspace->updateWindowData();
|
||||
}
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(monitorID());
|
||||
g_pCompositor->updateAllWindowsAnimatedDecorationValues();
|
||||
|
||||
@@ -873,8 +904,10 @@ void CWindow::destroyGroup() {
|
||||
m_sGroupData.pNextWindow.reset();
|
||||
m_sGroupData.head = false;
|
||||
updateWindowDecos();
|
||||
g_pCompositor->updateWorkspaceWindows(workspaceID());
|
||||
g_pCompositor->updateWorkspaceWindowData(workspaceID());
|
||||
if (m_pWorkspace) {
|
||||
m_pWorkspace->updateWindows();
|
||||
m_pWorkspace->updateWindowData();
|
||||
}
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(monitorID());
|
||||
g_pCompositor->updateAllWindowsAnimatedDecorationValues();
|
||||
|
||||
@@ -909,8 +942,10 @@ void CWindow::destroyGroup() {
|
||||
}
|
||||
g_pKeybindManager->m_bGroupsLocked = GROUPSLOCKEDPREV;
|
||||
|
||||
g_pCompositor->updateWorkspaceWindows(workspaceID());
|
||||
g_pCompositor->updateWorkspaceWindowData(workspaceID());
|
||||
if (m_pWorkspace) {
|
||||
m_pWorkspace->updateWindows();
|
||||
m_pWorkspace->updateWindowData();
|
||||
}
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(monitorID());
|
||||
g_pCompositor->updateAllWindowsAnimatedDecorationValues();
|
||||
|
||||
@@ -1168,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;
|
||||
@@ -1507,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;
|
||||
@@ -1519,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() {
|
||||
@@ -1558,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;
|
||||
@@ -1592,6 +1637,9 @@ 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() {
|
||||
@@ -1601,3 +1649,29 @@ bool CWindow::isX11OverrideRedirect() {
|
||||
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;
|
||||
@@ -186,6 +185,9 @@ struct SWindowData {
|
||||
CWindowOverridableVar<int> rounding;
|
||||
CWindowOverridableVar<int> borderSize;
|
||||
|
||||
CWindowOverridableVar<float> scrollMouse;
|
||||
CWindowOverridableVar<float> scrollTouchpad;
|
||||
|
||||
CWindowOverridableVar<std::string> animationStyle;
|
||||
CWindowOverridableVar<Vector2D> maxSize;
|
||||
CWindowOverridableVar<Vector2D> minSize;
|
||||
@@ -194,32 +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 szFullscreenState = ""; // empty means any
|
||||
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;
|
||||
};
|
||||
@@ -278,7 +260,7 @@ 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};
|
||||
SFullscreenState m_sFullscreenState = {.internal = FSMODE_NONE, .client = FSMODE_NONE};
|
||||
std::string m_szTitle = "";
|
||||
std::string m_szClass = "";
|
||||
std::string m_szInitialTitle = "";
|
||||
@@ -332,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;
|
||||
|
||||
@@ -340,8 +325,8 @@ class CWindow {
|
||||
|
||||
// Window decorations
|
||||
// TODO: make this a SP.
|
||||
std::deque<std::unique_ptr<IHyprWindowDecoration>> m_dWindowDecorations;
|
||||
std::vector<IHyprWindowDecoration*> m_vDecosToRemove;
|
||||
std::vector<std::unique_ptr<IHyprWindowDecoration>> m_dWindowDecorations;
|
||||
std::vector<IHyprWindowDecoration*> m_vDecosToRemove;
|
||||
|
||||
// Special render data, rules, etc
|
||||
SWindowData m_sWindowData;
|
||||
@@ -353,7 +338,7 @@ class CWindow {
|
||||
CAnimatedVariable<float> m_fActiveInactiveAlpha;
|
||||
|
||||
// animated shadow color
|
||||
CAnimatedVariable<CColor> m_cRealShadowColor;
|
||||
CAnimatedVariable<CHyprColor> m_cRealShadowColor;
|
||||
|
||||
// animated tint
|
||||
CAnimatedVariable<float> m_fDimPercent;
|
||||
@@ -391,24 +376,21 @@ 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;
|
||||
}
|
||||
|
||||
// methods
|
||||
CBox getFullWindowBoundingBox();
|
||||
SBoxExtents getFullWindowExtents();
|
||||
CBox getWindowBoxUnified(uint64_t props);
|
||||
inline CBox getWindowMainSurfaceBox() const {
|
||||
return {m_vRealPosition.value().x, m_vRealPosition.value().y, m_vRealSize.value().x, m_vRealSize.value().y};
|
||||
}
|
||||
CBox getFullWindowBoundingBox();
|
||||
SBoxExtents getFullWindowExtents();
|
||||
CBox getWindowBoxUnified(uint64_t props);
|
||||
CBox getWindowIdealBoundingBoxIgnoreReserved();
|
||||
void addWindowDeco(std::unique_ptr<IHyprWindowDecoration> deco);
|
||||
void updateWindowDecos();
|
||||
@@ -421,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();
|
||||
@@ -441,19 +423,17 @@ class CWindow {
|
||||
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();
|
||||
@@ -476,11 +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);
|
||||
|
90
src/desktop/WindowRule.cpp
Normal file
90
src/desktop/WindowRule.cpp
Normal file
@@ -0,0 +1,90 @@
|
||||
#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("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("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("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;
|
||||
}
|
||||
}
|
||||
}
|
60
src/desktop/WindowRule.hpp
Normal file
60
src/desktop/WindowRule.hpp
Normal file
@@ -0,0 +1,60 @@
|
||||
#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_CENTER,
|
||||
RULE_FULLSCREENSTATE,
|
||||
RULE_GROUP,
|
||||
RULE_IDLEINHIBIT,
|
||||
RULE_MAXSIZE,
|
||||
RULE_MINSIZE,
|
||||
RULE_MONITOR,
|
||||
RULE_MOVE,
|
||||
RULE_OPACITY,
|
||||
RULE_PLUGIN,
|
||||
RULE_PSEUDO,
|
||||
RULE_SIZE,
|
||||
RULE_SUPPRESSEVENT,
|
||||
RULE_TAG,
|
||||
RULE_WORKSPACE,
|
||||
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
|
||||
};
|
@@ -11,12 +11,9 @@ PHLWORKSPACE CWorkspace::create(WORKSPACEID id, PHLMONITOR monitor, std::string
|
||||
return workspace;
|
||||
}
|
||||
|
||||
CWorkspace::CWorkspace(WORKSPACEID id, PHLMONITOR monitor, std::string name, bool special, bool isEmpty) {
|
||||
m_pMonitor = monitor;
|
||||
m_iID = id;
|
||||
m_szName = name;
|
||||
m_bIsSpecialWorkspace = special;
|
||||
m_bWasCreatedEmpty = isEmpty;
|
||||
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) {
|
||||
@@ -106,7 +103,7 @@ void CWorkspace::startAnim(bool in, bool left, bool instant) {
|
||||
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));
|
||||
@@ -278,9 +275,9 @@ 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') {
|
||||
WORKSPACEID from = 0, to = 0;
|
||||
@@ -296,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)) {
|
||||
@@ -332,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;
|
||||
}
|
||||
@@ -367,7 +364,7 @@ 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;
|
||||
}
|
||||
@@ -422,18 +419,18 @@ 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),
|
||||
wantsCountVisible ? std::optional<bool>(wantsCountVisible) : std::nullopt);
|
||||
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),
|
||||
wantsCountVisible ? std::optional<bool>(wantsCountVisible) : std::nullopt);
|
||||
count = getWindows(wantsOnlyTiled == -1 ? std::nullopt : std::optional<bool>((bool)wantsOnlyTiled),
|
||||
wantsCountVisible ? std::optional<bool>(wantsCountVisible) : std::nullopt);
|
||||
|
||||
if (count != from)
|
||||
return false;
|
||||
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)) {
|
||||
@@ -456,11 +453,11 @@ bool CWorkspace::matchesStaticSelector(const std::string& selector_) {
|
||||
|
||||
WORKSPACEID count;
|
||||
if (wantsCountGroup)
|
||||
count = g_pCompositor->getGroupsOnWorkspace(m_iID, wantsOnlyTiled == -1 ? std::nullopt : std::optional<bool>((bool)wantsOnlyTiled),
|
||||
wantsCountVisible ? std::optional<bool>(wantsCountVisible) : std::nullopt);
|
||||
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),
|
||||
wantsCountVisible ? std::optional<bool>(wantsCountVisible) : std::nullopt);
|
||||
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)
|
||||
return false;
|
||||
@@ -525,3 +522,138 @@ bool CWorkspace::inert() {
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
@@ -63,23 +63,29 @@ class CWorkspace {
|
||||
|
||||
// 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 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();
|
||||
|
@@ -19,6 +19,7 @@ class IPointer : public IHID {
|
||||
struct SMotionEvent {
|
||||
uint32_t timeMs = 0;
|
||||
Vector2D delta, unaccel;
|
||||
bool mouse = false;
|
||||
};
|
||||
|
||||
struct SMotionAbsoluteEvent {
|
||||
@@ -31,6 +32,7 @@ class IPointer : public IHID {
|
||||
uint32_t timeMs = 0;
|
||||
uint32_t button = 0;
|
||||
wl_pointer_button_state state = WL_POINTER_BUTTON_STATE_PRESSED;
|
||||
bool mouse = false;
|
||||
};
|
||||
|
||||
struct SAxisEvent {
|
||||
@@ -40,6 +42,7 @@ class IPointer : public IHID {
|
||||
wl_pointer_axis_relative_direction relativeDirection = WL_POINTER_AXIS_RELATIVE_DIRECTION_IDENTICAL;
|
||||
double delta = 0.0;
|
||||
int32_t deltaDiscrete = 0;
|
||||
bool mouse = false;
|
||||
};
|
||||
|
||||
struct SSwipeBeginEvent {
|
||||
|
@@ -26,6 +26,7 @@ CMouse::CMouse(SP<Aquamarine::IPointer> mouse_) : mouse(mouse_) {
|
||||
.timeMs = E.timeMs,
|
||||
.delta = E.delta,
|
||||
.unaccel = E.unaccel,
|
||||
.mouse = true,
|
||||
});
|
||||
});
|
||||
|
||||
@@ -46,6 +47,7 @@ CMouse::CMouse(SP<Aquamarine::IPointer> mouse_) : mouse(mouse_) {
|
||||
.timeMs = E.timeMs,
|
||||
.button = E.button,
|
||||
.state = E.pressed ? WL_POINTER_BUTTON_STATE_PRESSED : WL_POINTER_BUTTON_STATE_RELEASED,
|
||||
.mouse = true,
|
||||
});
|
||||
});
|
||||
|
||||
@@ -59,6 +61,7 @@ CMouse::CMouse(SP<Aquamarine::IPointer> mouse_) : mouse(mouse_) {
|
||||
.relativeDirection = (wl_pointer_axis_relative_direction)E.direction,
|
||||
.delta = E.delta,
|
||||
.deltaDiscrete = E.discrete,
|
||||
.mouse = true,
|
||||
});
|
||||
});
|
||||
|
||||
|
@@ -3,7 +3,6 @@
|
||||
#include "IHID.hpp"
|
||||
#include "../macros.hpp"
|
||||
#include "../helpers/math/Math.hpp"
|
||||
#include "../helpers/math/Math.hpp"
|
||||
|
||||
AQUAMARINE_FORWARD(ITablet);
|
||||
AQUAMARINE_FORWARD(ITabletTool);
|
||||
@@ -27,7 +26,7 @@ class CTablet : public IHID {
|
||||
virtual eHIDType getType();
|
||||
SP<Aquamarine::ITablet> aq();
|
||||
|
||||
enum eTabletToolAxes {
|
||||
enum eTabletToolAxes : uint16_t {
|
||||
HID_TABLET_TOOL_AXIS_X = (1 << 0),
|
||||
HID_TABLET_TOOL_AXIS_Y = (1 << 1),
|
||||
HID_TABLET_TOOL_AXIS_TILT_X = (1 << 2),
|
||||
@@ -92,9 +91,10 @@ class CTablet : public IHID {
|
||||
WP<CTablet> self;
|
||||
|
||||
bool relativeInput = false;
|
||||
bool absolutePos = false;
|
||||
std::string boundOutput = "";
|
||||
CBox activeArea;
|
||||
CBox boundBox; // output-local
|
||||
CBox boundBox;
|
||||
|
||||
private:
|
||||
CTablet(SP<Aquamarine::ITablet> tablet);
|
||||
@@ -172,7 +172,7 @@ class CTabletTool : public IHID {
|
||||
static SP<CTabletTool> create(SP<Aquamarine::ITabletTool> tool);
|
||||
~CTabletTool();
|
||||
|
||||
enum eTabletToolType {
|
||||
enum eTabletToolType : uint8_t {
|
||||
HID_TABLET_TOOL_TYPE_PEN = 1,
|
||||
HID_TABLET_TOOL_TYPE_ERASER,
|
||||
HID_TABLET_TOOL_TYPE_BRUSH,
|
||||
@@ -183,7 +183,7 @@ class CTabletTool : public IHID {
|
||||
HID_TABLET_TOOL_TYPE_TOTEM,
|
||||
};
|
||||
|
||||
enum eTabletToolCapabilities {
|
||||
enum eTabletToolCapabilities : uint8_t {
|
||||
HID_TABLET_TOOL_CAPABILITY_TILT = (1 << 0),
|
||||
HID_TABLET_TOOL_CAPABILITY_PRESSURE = (1 << 1),
|
||||
HID_TABLET_TOOL_CAPABILITY_DISTANCE = (1 << 2),
|
||||
|
@@ -38,7 +38,7 @@ CVirtualPointer::CVirtualPointer(SP<CVirtualPointerV1Resource> resource) : point
|
||||
listeners.holdBegin = pointer->events.holdBegin.registerListener([this](std::any d) { pointerEvents.holdBegin.emit(d); });
|
||||
listeners.holdEnd = pointer->events.holdEnd.registerListener([this](std::any d) { pointerEvents.holdEnd.emit(d); });
|
||||
|
||||
boundOutput = resource->boundOutput ? resource->boundOutput->szName : "entire";
|
||||
boundOutput = resource->boundOutput ? resource->boundOutput->szName : "";
|
||||
|
||||
deviceName = pointer->name;
|
||||
}
|
||||
|
@@ -1,12 +1,7 @@
|
||||
#pragma once
|
||||
#include "../defines.hpp"
|
||||
|
||||
//
|
||||
// LISTEN_NAME -> the wl_listener
|
||||
//
|
||||
// LISTENER_NAME -> the wl_listener.notify function
|
||||
//
|
||||
|
||||
// NOLINTNEXTLINE(readability-identifier-naming)
|
||||
namespace Events {
|
||||
// Window events
|
||||
DYNLISTENFUNC(commitWindow);
|
||||
|
@@ -134,149 +134,178 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
// window rules
|
||||
PWINDOW->m_vMatchedRules = g_pConfigManager->getMatchingRules(PWINDOW, false);
|
||||
std::optional<eFullscreenMode> requestedInternalFSMode, requestedClientFSMode;
|
||||
std::optional<sFullscreenState> requestedFSState;
|
||||
std::optional<SFullscreenState> requestedFSState;
|
||||
if (PWINDOW->m_bWantsInitialFullscreen || (PWINDOW->m_bIsX11 && PWINDOW->m_pXWaylandSurface->fullscreen))
|
||||
requestedClientFSMode = FSMODE_FULLSCREEN;
|
||||
|
||||
for (auto const& r : PWINDOW->m_vMatchedRules) {
|
||||
if (r.szRule.starts_with("monitor")) {
|
||||
try {
|
||||
const auto MONITORSTR = trim(r.szRule.substr(r.szRule.find(' ')));
|
||||
switch (r->ruleType) {
|
||||
case CWindowRule::RULE_MONITOR: {
|
||||
try {
|
||||
const auto MONITORSTR = trim(r->szRule.substr(r->szRule.find(' ')));
|
||||
|
||||
if (MONITORSTR == "unset") {
|
||||
PWINDOW->m_pMonitor = PMONITOR;
|
||||
} else {
|
||||
if (isNumber(MONITORSTR)) {
|
||||
const MONITORID MONITOR = std::stoi(MONITORSTR);
|
||||
if (const auto PM = g_pCompositor->getMonitorFromID(MONITOR); PM)
|
||||
PWINDOW->m_pMonitor = PM;
|
||||
else
|
||||
PWINDOW->m_pMonitor = g_pCompositor->m_vMonitors.at(0);
|
||||
if (MONITORSTR == "unset") {
|
||||
PWINDOW->m_pMonitor = PMONITOR;
|
||||
} else {
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromName(MONITORSTR);
|
||||
if (PMONITOR)
|
||||
PWINDOW->m_pMonitor = PMONITOR;
|
||||
else {
|
||||
Debug::log(ERR, "No monitor in monitor {} rule", MONITORSTR);
|
||||
continue;
|
||||
if (isNumber(MONITORSTR)) {
|
||||
const MONITORID MONITOR = std::stoi(MONITORSTR);
|
||||
if (const auto PM = g_pCompositor->getMonitorFromID(MONITOR); PM)
|
||||
PWINDOW->m_pMonitor = PM;
|
||||
else
|
||||
PWINDOW->m_pMonitor = g_pCompositor->m_vMonitors.at(0);
|
||||
} else {
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromName(MONITORSTR);
|
||||
if (PMONITOR)
|
||||
PWINDOW->m_pMonitor = PMONITOR;
|
||||
else {
|
||||
Debug::log(ERR, "No monitor in monitor {} rule", MONITORSTR);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const auto PMONITORFROMID = PWINDOW->m_pMonitor.lock();
|
||||
|
||||
if (PWINDOW->m_pMonitor != PMONITOR) {
|
||||
g_pKeybindManager->m_mDispatchers["focusmonitor"](std::to_string(PWINDOW->monitorID()));
|
||||
PMONITOR = PMONITORFROMID;
|
||||
}
|
||||
PWINDOW->m_pWorkspace = PMONITOR->activeSpecialWorkspace ? PMONITOR->activeSpecialWorkspace : PMONITOR->activeWorkspace;
|
||||
|
||||
Debug::log(LOG, "Rule monitor, applying to {:mw}", PWINDOW);
|
||||
} catch (std::exception& e) { Debug::log(ERR, "Rule monitor failed, rule: {} -> {} | err: {}", r->szRule, r->szValue, e.what()); }
|
||||
break;
|
||||
}
|
||||
case CWindowRule::RULE_WORKSPACE: {
|
||||
// check if it isnt unset
|
||||
const auto WORKSPACERQ = r->szRule.substr(r->szRule.find_first_of(' ') + 1);
|
||||
|
||||
if (WORKSPACERQ == "unset") {
|
||||
requestedWorkspace = "";
|
||||
} else {
|
||||
requestedWorkspace = WORKSPACERQ;
|
||||
}
|
||||
|
||||
const auto PMONITORFROMID = PWINDOW->m_pMonitor.lock();
|
||||
const auto JUSTWORKSPACE = WORKSPACERQ.contains(' ') ? WORKSPACERQ.substr(0, WORKSPACERQ.find_first_of(' ')) : WORKSPACERQ;
|
||||
|
||||
if (PWINDOW->m_pMonitor != PMONITOR) {
|
||||
g_pKeybindManager->m_mDispatchers["focusmonitor"](std::to_string(PWINDOW->monitorID()));
|
||||
PMONITOR = PMONITORFROMID;
|
||||
if (JUSTWORKSPACE == PWORKSPACE->m_szName || JUSTWORKSPACE == "name:" + PWORKSPACE->m_szName)
|
||||
requestedWorkspace = "";
|
||||
|
||||
Debug::log(LOG, "Rule workspace matched by {}, {} applied.", PWINDOW, r->szValue);
|
||||
break;
|
||||
}
|
||||
case CWindowRule::RULE_FLOAT: {
|
||||
PWINDOW->m_bIsFloating = true;
|
||||
break;
|
||||
}
|
||||
case CWindowRule::RULE_TILE: {
|
||||
PWINDOW->m_bIsFloating = false;
|
||||
break;
|
||||
}
|
||||
case CWindowRule::RULE_PSEUDO: {
|
||||
PWINDOW->m_bIsPseudotiled = true;
|
||||
break;
|
||||
}
|
||||
case CWindowRule::RULE_NOINITIALFOCUS: {
|
||||
PWINDOW->m_bNoInitialFocus = true;
|
||||
break;
|
||||
}
|
||||
case CWindowRule::RULE_FULLSCREENSTATE: {
|
||||
const auto ARGS = CVarList(r->szRule.substr(r->szRule.find_first_of(' ') + 1), 2, ' ');
|
||||
int internalMode, clientMode;
|
||||
try {
|
||||
internalMode = std::stoi(ARGS[0]);
|
||||
} catch (std::exception& e) { internalMode = 0; }
|
||||
try {
|
||||
clientMode = std::stoi(ARGS[1]);
|
||||
} catch (std::exception& e) { clientMode = 0; }
|
||||
requestedFSState = SFullscreenState{.internal = (eFullscreenMode)internalMode, .client = (eFullscreenMode)clientMode};
|
||||
break;
|
||||
}
|
||||
case CWindowRule::RULE_SUPPRESSEVENT: {
|
||||
CVarList vars(r->szRule, 0, 's', true);
|
||||
for (size_t i = 1; i < vars.size(); ++i) {
|
||||
if (vars[i] == "fullscreen")
|
||||
PWINDOW->m_eSuppressedEvents |= SUPPRESS_FULLSCREEN;
|
||||
else if (vars[i] == "maximize")
|
||||
PWINDOW->m_eSuppressedEvents |= SUPPRESS_MAXIMIZE;
|
||||
else if (vars[i] == "activate")
|
||||
PWINDOW->m_eSuppressedEvents |= SUPPRESS_ACTIVATE;
|
||||
else if (vars[i] == "activatefocus")
|
||||
PWINDOW->m_eSuppressedEvents |= SUPPRESS_ACTIVATE_FOCUSONLY;
|
||||
else
|
||||
Debug::log(ERR, "Error while parsing suppressevent windowrule: unknown event type {}", vars[i]);
|
||||
}
|
||||
PWINDOW->m_pWorkspace = PMONITOR->activeSpecialWorkspace ? PMONITOR->activeSpecialWorkspace : PMONITOR->activeWorkspace;
|
||||
|
||||
Debug::log(LOG, "Rule monitor, applying to {:mw}", PWINDOW);
|
||||
} catch (std::exception& e) { Debug::log(ERR, "Rule monitor failed, rule: {} -> {} | err: {}", r.szRule, r.szValue, e.what()); }
|
||||
} else if (r.szRule.starts_with("workspace")) {
|
||||
// check if it isnt unset
|
||||
const auto WORKSPACERQ = r.szRule.substr(r.szRule.find_first_of(' ') + 1);
|
||||
|
||||
if (WORKSPACERQ == "unset") {
|
||||
requestedWorkspace = "";
|
||||
} else {
|
||||
requestedWorkspace = WORKSPACERQ;
|
||||
break;
|
||||
}
|
||||
|
||||
const auto JUSTWORKSPACE = WORKSPACERQ.contains(' ') ? WORKSPACERQ.substr(0, WORKSPACERQ.find_first_of(' ')) : WORKSPACERQ;
|
||||
|
||||
if (JUSTWORKSPACE == PWORKSPACE->m_szName || JUSTWORKSPACE == "name:" + PWORKSPACE->m_szName)
|
||||
requestedWorkspace = "";
|
||||
|
||||
Debug::log(LOG, "Rule workspace matched by {}, {} applied.", PWINDOW, r.szValue);
|
||||
} else if (r.szRule.starts_with("float")) {
|
||||
PWINDOW->m_bIsFloating = true;
|
||||
} else if (r.szRule.starts_with("tile")) {
|
||||
PWINDOW->m_bIsFloating = false;
|
||||
} else if (r.szRule.starts_with("pseudo")) {
|
||||
PWINDOW->m_bIsPseudotiled = true;
|
||||
} else if (r.szRule.starts_with("noinitialfocus")) {
|
||||
PWINDOW->m_bNoInitialFocus = true;
|
||||
} else if (r.szRule.starts_with("fullscreenstate")) {
|
||||
const auto ARGS = CVarList(r.szRule.substr(r.szRule.find_first_of(' ') + 1), 2, ' ');
|
||||
int internalMode, clientMode;
|
||||
try {
|
||||
internalMode = std::stoi(ARGS[0]);
|
||||
} catch (std::exception& e) { internalMode = 0; }
|
||||
try {
|
||||
clientMode = std::stoi(ARGS[1]);
|
||||
} catch (std::exception& e) { clientMode = 0; }
|
||||
requestedFSState = sFullscreenState{.internal = (eFullscreenMode)internalMode, .client = (eFullscreenMode)clientMode};
|
||||
} else if (r.szRule.starts_with("suppressevent")) {
|
||||
CVarList vars(r.szRule, 0, 's', true);
|
||||
for (size_t i = 1; i < vars.size(); ++i) {
|
||||
if (vars[i] == "fullscreen")
|
||||
PWINDOW->m_eSuppressedEvents |= SUPPRESS_FULLSCREEN;
|
||||
else if (vars[i] == "maximize")
|
||||
PWINDOW->m_eSuppressedEvents |= SUPPRESS_MAXIMIZE;
|
||||
else if (vars[i] == "activate")
|
||||
PWINDOW->m_eSuppressedEvents |= SUPPRESS_ACTIVATE;
|
||||
else if (vars[i] == "activatefocus")
|
||||
PWINDOW->m_eSuppressedEvents |= SUPPRESS_ACTIVATE_FOCUSONLY;
|
||||
else
|
||||
Debug::log(ERR, "Error while parsing suppressevent windowrule: unknown event type {}", vars[i]);
|
||||
case CWindowRule::RULE_PIN: {
|
||||
PWINDOW->m_bPinned = true;
|
||||
break;
|
||||
}
|
||||
} else if (r.szRule == "pin") {
|
||||
PWINDOW->m_bPinned = true;
|
||||
} else if (r.szRule == "fullscreen") {
|
||||
requestedInternalFSMode = FSMODE_FULLSCREEN;
|
||||
} else if (r.szRule == "maximize") {
|
||||
requestedInternalFSMode = FSMODE_MAXIMIZED;
|
||||
} else if (r.szRule == "stayfocused") {
|
||||
PWINDOW->m_bStayFocused = true;
|
||||
} else if (r.szRule.starts_with("group")) {
|
||||
if (PWINDOW->m_eGroupRules & GROUP_OVERRIDE)
|
||||
continue;
|
||||
|
||||
// `group` is a shorthand of `group set`
|
||||
if (trim(r.szRule) == "group") {
|
||||
PWINDOW->m_eGroupRules |= GROUP_SET;
|
||||
continue;
|
||||
case CWindowRule::RULE_FULLSCREEN: {
|
||||
requestedInternalFSMode = FSMODE_FULLSCREEN;
|
||||
break;
|
||||
}
|
||||
|
||||
CVarList vars(r.szRule, 0, 's');
|
||||
std::string vPrev = "";
|
||||
|
||||
for (auto const& v : vars) {
|
||||
if (v == "group")
|
||||
case CWindowRule::RULE_MAXIMIZE: {
|
||||
requestedInternalFSMode = FSMODE_MAXIMIZED;
|
||||
break;
|
||||
}
|
||||
case CWindowRule::RULE_STAYFOCUSED: {
|
||||
PWINDOW->m_bStayFocused = true;
|
||||
break;
|
||||
}
|
||||
case CWindowRule::RULE_GROUP: {
|
||||
if (PWINDOW->m_eGroupRules & GROUP_OVERRIDE)
|
||||
continue;
|
||||
|
||||
if (v == "set") {
|
||||
// `group` is a shorthand of `group set`
|
||||
if (trim(r->szRule) == "group") {
|
||||
PWINDOW->m_eGroupRules |= GROUP_SET;
|
||||
} else if (v == "new") {
|
||||
// shorthand for `group barred set`
|
||||
PWINDOW->m_eGroupRules |= (GROUP_SET | GROUP_BARRED);
|
||||
} else if (v == "lock") {
|
||||
PWINDOW->m_eGroupRules |= GROUP_LOCK;
|
||||
} else if (v == "invade") {
|
||||
PWINDOW->m_eGroupRules |= GROUP_INVADE;
|
||||
} else if (v == "barred") {
|
||||
PWINDOW->m_eGroupRules |= GROUP_BARRED;
|
||||
} else if (v == "deny") {
|
||||
PWINDOW->m_sGroupData.deny = true;
|
||||
} else if (v == "override") {
|
||||
// Clear existing rules
|
||||
PWINDOW->m_eGroupRules = GROUP_OVERRIDE;
|
||||
} else if (v == "unset") {
|
||||
// Clear existing rules and stop processing
|
||||
PWINDOW->m_eGroupRules = GROUP_OVERRIDE;
|
||||
break;
|
||||
} else if (v == "always") {
|
||||
if (vPrev == "set" || vPrev == "group")
|
||||
PWINDOW->m_eGroupRules |= GROUP_SET_ALWAYS;
|
||||
else if (vPrev == "lock")
|
||||
PWINDOW->m_eGroupRules |= GROUP_LOCK_ALWAYS;
|
||||
else
|
||||
Debug::log(ERR, "windowrule `group` does not support `{} always`", vPrev);
|
||||
continue;
|
||||
}
|
||||
vPrev = v;
|
||||
|
||||
CVarList vars(r->szRule, 0, 's');
|
||||
std::string vPrev = "";
|
||||
|
||||
for (auto const& v : vars) {
|
||||
if (v == "group")
|
||||
continue;
|
||||
|
||||
if (v == "set") {
|
||||
PWINDOW->m_eGroupRules |= GROUP_SET;
|
||||
} else if (v == "new") {
|
||||
// shorthand for `group barred set`
|
||||
PWINDOW->m_eGroupRules |= (GROUP_SET | GROUP_BARRED);
|
||||
} else if (v == "lock") {
|
||||
PWINDOW->m_eGroupRules |= GROUP_LOCK;
|
||||
} else if (v == "invade") {
|
||||
PWINDOW->m_eGroupRules |= GROUP_INVADE;
|
||||
} else if (v == "barred") {
|
||||
PWINDOW->m_eGroupRules |= GROUP_BARRED;
|
||||
} else if (v == "deny") {
|
||||
PWINDOW->m_sGroupData.deny = true;
|
||||
} else if (v == "override") {
|
||||
// Clear existing rules
|
||||
PWINDOW->m_eGroupRules = GROUP_OVERRIDE;
|
||||
} else if (v == "unset") {
|
||||
// Clear existing rules and stop processing
|
||||
PWINDOW->m_eGroupRules = GROUP_OVERRIDE;
|
||||
break;
|
||||
} else if (v == "always") {
|
||||
if (vPrev == "set" || vPrev == "group")
|
||||
PWINDOW->m_eGroupRules |= GROUP_SET_ALWAYS;
|
||||
else if (vPrev == "lock")
|
||||
PWINDOW->m_eGroupRules |= GROUP_LOCK_ALWAYS;
|
||||
else
|
||||
Debug::log(ERR, "windowrule `group` does not support `{} always`", vPrev);
|
||||
}
|
||||
vPrev = v;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
|
||||
PWINDOW->applyDynamicRule(r);
|
||||
}
|
||||
|
||||
@@ -296,7 +325,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
auto pWorkspace = g_pCompositor->getWorkspaceByID(REQUESTEDWORKSPACEID);
|
||||
|
||||
if (!pWorkspace)
|
||||
pWorkspace = g_pCompositor->createNewWorkspace(REQUESTEDWORKSPACEID, PWINDOW->monitorID(), requestedWorkspaceName);
|
||||
pWorkspace = g_pCompositor->createNewWorkspace(REQUESTEDWORKSPACEID, PWINDOW->monitorID(), requestedWorkspaceName, false);
|
||||
|
||||
PWORKSPACE = pWorkspace;
|
||||
|
||||
@@ -330,125 +359,133 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
|
||||
// size and move rules
|
||||
for (auto const& r : PWINDOW->m_vMatchedRules) {
|
||||
if (r.szRule.starts_with("size")) {
|
||||
try {
|
||||
switch (r->ruleType) {
|
||||
case CWindowRule::RULE_SIZE: {
|
||||
try {
|
||||
auto stringToFloatClamp = [](const std::string& VALUE, const float CURR, const float REL) {
|
||||
if (VALUE.starts_with('<'))
|
||||
return std::min(CURR, stringToPercentage(VALUE.substr(1, VALUE.length() - 1), REL));
|
||||
else if (VALUE.starts_with('>'))
|
||||
return std::max(CURR, stringToPercentage(VALUE.substr(1, VALUE.length() - 1), REL));
|
||||
|
||||
auto stringToFloatClamp = [](const std::string& VALUE, const float CURR, const float REL) {
|
||||
if (VALUE.starts_with('<'))
|
||||
return std::min(CURR, stringToPercentage(VALUE.substr(1, VALUE.length() - 1), REL));
|
||||
else if (VALUE.starts_with('>'))
|
||||
return std::max(CURR, stringToPercentage(VALUE.substr(1, VALUE.length() - 1), REL));
|
||||
return stringToPercentage(VALUE, REL);
|
||||
};
|
||||
|
||||
return stringToPercentage(VALUE, REL);
|
||||
};
|
||||
const auto VALUE = r->szRule.substr(r->szRule.find(' ') + 1);
|
||||
const auto SIZEXSTR = VALUE.substr(0, VALUE.find(' '));
|
||||
const auto SIZEYSTR = VALUE.substr(VALUE.find(' ') + 1);
|
||||
|
||||
const auto VALUE = r.szRule.substr(r.szRule.find(' ') + 1);
|
||||
const auto SIZEXSTR = VALUE.substr(0, VALUE.find(' '));
|
||||
const auto SIZEYSTR = VALUE.substr(VALUE.find(' ') + 1);
|
||||
const auto MAXSIZE = PWINDOW->requestedMaxSize();
|
||||
|
||||
const auto MAXSIZE = g_pXWaylandManager->getMaxSizeForWindow(PWINDOW);
|
||||
const float SIZEX = SIZEXSTR == "max" ? std::clamp(MAXSIZE.x, MIN_WINDOW_SIZE, PMONITOR->vecSize.x) :
|
||||
stringToFloatClamp(SIZEXSTR, PWINDOW->m_vRealSize.goal().x, PMONITOR->vecSize.x);
|
||||
|
||||
const float SIZEX = SIZEXSTR == "max" ? std::clamp(MAXSIZE.x, MIN_WINDOW_SIZE, PMONITOR->vecSize.x) :
|
||||
stringToFloatClamp(SIZEXSTR, PWINDOW->m_vRealSize.goal().x, PMONITOR->vecSize.x);
|
||||
const float SIZEY = SIZEYSTR == "max" ? std::clamp(MAXSIZE.y, MIN_WINDOW_SIZE, PMONITOR->vecSize.y) :
|
||||
stringToFloatClamp(SIZEYSTR, PWINDOW->m_vRealSize.goal().y, PMONITOR->vecSize.y);
|
||||
|
||||
const float SIZEY = SIZEYSTR == "max" ? std::clamp(MAXSIZE.y, MIN_WINDOW_SIZE, PMONITOR->vecSize.y) :
|
||||
stringToFloatClamp(SIZEYSTR, PWINDOW->m_vRealSize.goal().y, PMONITOR->vecSize.y);
|
||||
Debug::log(LOG, "Rule size, applying to {}", PWINDOW);
|
||||
|
||||
Debug::log(LOG, "Rule size, applying to {}", PWINDOW);
|
||||
PWINDOW->clampWindowSize(Vector2D{SIZEXSTR.starts_with("<") ? 0 : SIZEX, SIZEYSTR.starts_with("<") ? 0 : SIZEY}, Vector2D{SIZEX, SIZEY});
|
||||
|
||||
PWINDOW->clampWindowSize(Vector2D{SIZEXSTR.starts_with("<") ? 0 : SIZEX, SIZEYSTR.starts_with("<") ? 0 : SIZEY}, Vector2D{SIZEX, SIZEY});
|
||||
PWINDOW->setHidden(false);
|
||||
} catch (...) { Debug::log(LOG, "Rule size failed, rule: {} -> {}", r->szRule, r->szValue); }
|
||||
break;
|
||||
}
|
||||
case CWindowRule::RULE_MOVE: {
|
||||
try {
|
||||
auto value = r->szRule.substr(r->szRule.find(' ') + 1);
|
||||
|
||||
PWINDOW->setHidden(false);
|
||||
} catch (...) { Debug::log(LOG, "Rule size failed, rule: {} -> {}", r.szRule, r.szValue); }
|
||||
} else if (r.szRule.starts_with("move")) {
|
||||
try {
|
||||
auto value = r.szRule.substr(r.szRule.find(' ') + 1);
|
||||
const bool ONSCREEN = value.starts_with("onscreen");
|
||||
|
||||
const bool ONSCREEN = value.starts_with("onscreen");
|
||||
if (ONSCREEN)
|
||||
value = value.substr(value.find_first_of(' ') + 1);
|
||||
|
||||
if (ONSCREEN)
|
||||
value = value.substr(value.find_first_of(' ') + 1);
|
||||
|
||||
const bool CURSOR = value.starts_with("cursor");
|
||||
|
||||
if (CURSOR)
|
||||
value = value.substr(value.find_first_of(' ') + 1);
|
||||
|
||||
const auto POSXSTR = value.substr(0, value.find(' '));
|
||||
const auto POSYSTR = value.substr(value.find(' ') + 1);
|
||||
|
||||
int posX = 0;
|
||||
int posY = 0;
|
||||
|
||||
if (POSXSTR.starts_with("100%-")) {
|
||||
const bool subtractWindow = POSXSTR.starts_with("100%-w-");
|
||||
const auto POSXRAW = (subtractWindow) ? POSXSTR.substr(7) : POSXSTR.substr(5);
|
||||
posX =
|
||||
PMONITOR->vecSize.x - (!POSXRAW.contains('%') ? std::stoi(POSXRAW) : std::stof(POSXRAW.substr(0, POSXRAW.length() - 1)) * 0.01 * PMONITOR->vecSize.x);
|
||||
|
||||
if (subtractWindow)
|
||||
posX -= PWINDOW->m_vRealSize.goal().x;
|
||||
const bool CURSOR = value.starts_with("cursor");
|
||||
|
||||
if (CURSOR)
|
||||
Debug::log(ERR, "Cursor is not compatible with 100%-, ignoring cursor!");
|
||||
} else if (!CURSOR) {
|
||||
posX = !POSXSTR.contains('%') ? std::stoi(POSXSTR) : std::stof(POSXSTR.substr(0, POSXSTR.length() - 1)) * 0.01 * PMONITOR->vecSize.x;
|
||||
} else {
|
||||
// cursor
|
||||
if (POSXSTR == "cursor") {
|
||||
posX = g_pInputManager->getMouseCoordsInternal().x - PMONITOR->vecPosition.x;
|
||||
value = value.substr(value.find_first_of(' ') + 1);
|
||||
|
||||
const auto POSXSTR = value.substr(0, value.find(' '));
|
||||
const auto POSYSTR = value.substr(value.find(' ') + 1);
|
||||
|
||||
int posX = 0;
|
||||
int posY = 0;
|
||||
|
||||
if (POSXSTR.starts_with("100%-")) {
|
||||
const bool subtractWindow = POSXSTR.starts_with("100%-w-");
|
||||
const auto POSXRAW = (subtractWindow) ? POSXSTR.substr(7) : POSXSTR.substr(5);
|
||||
posX = PMONITOR->vecSize.x -
|
||||
(!POSXRAW.contains('%') ? std::stoi(POSXRAW) : std::stof(POSXRAW.substr(0, POSXRAW.length() - 1)) * 0.01 * PMONITOR->vecSize.x);
|
||||
|
||||
if (subtractWindow)
|
||||
posX -= PWINDOW->m_vRealSize.goal().x;
|
||||
|
||||
if (CURSOR)
|
||||
Debug::log(ERR, "Cursor is not compatible with 100%-, ignoring cursor!");
|
||||
} else if (!CURSOR) {
|
||||
posX = !POSXSTR.contains('%') ? std::stoi(POSXSTR) : std::stof(POSXSTR.substr(0, POSXSTR.length() - 1)) * 0.01 * PMONITOR->vecSize.x;
|
||||
} else {
|
||||
posX = g_pInputManager->getMouseCoordsInternal().x - PMONITOR->vecPosition.x +
|
||||
(!POSXSTR.contains('%') ? std::stoi(POSXSTR) : std::stof(POSXSTR.substr(0, POSXSTR.length() - 1)) * 0.01 * PWINDOW->m_vRealSize.goal().x);
|
||||
// cursor
|
||||
if (POSXSTR == "cursor") {
|
||||
posX = g_pInputManager->getMouseCoordsInternal().x - PMONITOR->vecPosition.x;
|
||||
} else {
|
||||
posX = g_pInputManager->getMouseCoordsInternal().x - PMONITOR->vecPosition.x +
|
||||
(!POSXSTR.contains('%') ? std::stoi(POSXSTR) : std::stof(POSXSTR.substr(0, POSXSTR.length() - 1)) * 0.01 * PWINDOW->m_vRealSize.goal().x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (POSYSTR.starts_with("100%-")) {
|
||||
const bool subtractWindow = POSYSTR.starts_with("100%-w-");
|
||||
const auto POSYRAW = (subtractWindow) ? POSYSTR.substr(7) : POSYSTR.substr(5);
|
||||
posY =
|
||||
PMONITOR->vecSize.y - (!POSYRAW.contains('%') ? std::stoi(POSYRAW) : std::stof(POSYRAW.substr(0, POSYRAW.length() - 1)) * 0.01 * PMONITOR->vecSize.y);
|
||||
if (POSYSTR.starts_with("100%-")) {
|
||||
const bool subtractWindow = POSYSTR.starts_with("100%-w-");
|
||||
const auto POSYRAW = (subtractWindow) ? POSYSTR.substr(7) : POSYSTR.substr(5);
|
||||
posY = PMONITOR->vecSize.y -
|
||||
(!POSYRAW.contains('%') ? std::stoi(POSYRAW) : std::stof(POSYRAW.substr(0, POSYRAW.length() - 1)) * 0.01 * PMONITOR->vecSize.y);
|
||||
|
||||
if (subtractWindow)
|
||||
posY -= PWINDOW->m_vRealSize.goal().y;
|
||||
if (subtractWindow)
|
||||
posY -= PWINDOW->m_vRealSize.goal().y;
|
||||
|
||||
if (CURSOR)
|
||||
Debug::log(ERR, "Cursor is not compatible with 100%-, ignoring cursor!");
|
||||
} else if (!CURSOR) {
|
||||
posY = !POSYSTR.contains('%') ? std::stoi(POSYSTR) : std::stof(POSYSTR.substr(0, POSYSTR.length() - 1)) * 0.01 * PMONITOR->vecSize.y;
|
||||
} else {
|
||||
// cursor
|
||||
if (POSYSTR == "cursor") {
|
||||
posY = g_pInputManager->getMouseCoordsInternal().y - PMONITOR->vecPosition.y;
|
||||
if (CURSOR)
|
||||
Debug::log(ERR, "Cursor is not compatible with 100%-, ignoring cursor!");
|
||||
} else if (!CURSOR) {
|
||||
posY = !POSYSTR.contains('%') ? std::stoi(POSYSTR) : std::stof(POSYSTR.substr(0, POSYSTR.length() - 1)) * 0.01 * PMONITOR->vecSize.y;
|
||||
} else {
|
||||
posY = g_pInputManager->getMouseCoordsInternal().y - PMONITOR->vecPosition.y +
|
||||
(!POSYSTR.contains('%') ? std::stoi(POSYSTR) : std::stof(POSYSTR.substr(0, POSYSTR.length() - 1)) * 0.01 * PWINDOW->m_vRealSize.goal().y);
|
||||
// cursor
|
||||
if (POSYSTR == "cursor") {
|
||||
posY = g_pInputManager->getMouseCoordsInternal().y - PMONITOR->vecPosition.y;
|
||||
} else {
|
||||
posY = g_pInputManager->getMouseCoordsInternal().y - PMONITOR->vecPosition.y +
|
||||
(!POSYSTR.contains('%') ? std::stoi(POSYSTR) : std::stof(POSYSTR.substr(0, POSYSTR.length() - 1)) * 0.01 * PWINDOW->m_vRealSize.goal().y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ONSCREEN) {
|
||||
int borderSize = PWINDOW->getRealBorderSize();
|
||||
if (ONSCREEN) {
|
||||
int borderSize = PWINDOW->getRealBorderSize();
|
||||
|
||||
posX = std::clamp(posX, (int)(PMONITOR->vecReservedTopLeft.x + borderSize),
|
||||
(int)(PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x - PWINDOW->m_vRealSize.goal().x - borderSize));
|
||||
posX = std::clamp(posX, (int)(PMONITOR->vecReservedTopLeft.x + borderSize),
|
||||
(int)(PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x - PWINDOW->m_vRealSize.goal().x - borderSize));
|
||||
|
||||
posY = std::clamp(posY, (int)(PMONITOR->vecReservedTopLeft.y + borderSize),
|
||||
(int)(PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y - PWINDOW->m_vRealSize.goal().y - borderSize));
|
||||
}
|
||||
posY = std::clamp(posY, (int)(PMONITOR->vecReservedTopLeft.y + borderSize),
|
||||
(int)(PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y - PWINDOW->m_vRealSize.goal().y - borderSize));
|
||||
}
|
||||
|
||||
Debug::log(LOG, "Rule move, applying to {}", PWINDOW);
|
||||
Debug::log(LOG, "Rule move, applying to {}", PWINDOW);
|
||||
|
||||
PWINDOW->m_vRealPosition = Vector2D(posX, posY) + PMONITOR->vecPosition;
|
||||
PWINDOW->m_vRealPosition = Vector2D(posX, posY) + PMONITOR->vecPosition;
|
||||
|
||||
PWINDOW->setHidden(false);
|
||||
} catch (...) { Debug::log(LOG, "Rule move failed, rule: {} -> {}", r.szRule, r.szValue); }
|
||||
} else if (r.szRule.starts_with("center")) {
|
||||
auto RESERVEDOFFSET = Vector2D();
|
||||
const auto ARGS = CVarList(r.szRule, 2, ' ');
|
||||
if (ARGS[1] == "1")
|
||||
RESERVEDOFFSET = (PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight) / 2.f;
|
||||
PWINDOW->setHidden(false);
|
||||
} catch (...) { Debug::log(LOG, "Rule move failed, rule: {} -> {}", r->szRule, r->szValue); }
|
||||
break;
|
||||
}
|
||||
case CWindowRule::RULE_CENTER: {
|
||||
auto RESERVEDOFFSET = Vector2D();
|
||||
const auto ARGS = CVarList(r->szRule, 2, ' ');
|
||||
if (ARGS[1] == "1")
|
||||
RESERVEDOFFSET = (PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight) / 2.f;
|
||||
|
||||
PWINDOW->m_vRealPosition = PMONITOR->middle() - PWINDOW->m_vRealSize.goal() / 2.f + RESERVEDOFFSET;
|
||||
PWINDOW->m_vRealPosition = PMONITOR->middle() - PWINDOW->m_vRealSize.goal() / 2.f + RESERVEDOFFSET;
|
||||
break;
|
||||
}
|
||||
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -463,26 +500,27 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
bool setPseudo = false;
|
||||
|
||||
for (auto const& r : PWINDOW->m_vMatchedRules) {
|
||||
if (r.szRule.starts_with("size")) {
|
||||
try {
|
||||
const auto VALUE = r.szRule.substr(r.szRule.find(' ') + 1);
|
||||
const auto SIZEXSTR = VALUE.substr(0, VALUE.find(' '));
|
||||
const auto SIZEYSTR = VALUE.substr(VALUE.find(' ') + 1);
|
||||
if (r->ruleType != CWindowRule::RULE_SIZE)
|
||||
continue;
|
||||
|
||||
const auto MAXSIZE = g_pXWaylandManager->getMaxSizeForWindow(PWINDOW);
|
||||
try {
|
||||
const auto VALUE = r->szRule.substr(r->szRule.find(' ') + 1);
|
||||
const auto SIZEXSTR = VALUE.substr(0, VALUE.find(' '));
|
||||
const auto SIZEYSTR = VALUE.substr(VALUE.find(' ') + 1);
|
||||
|
||||
const float SIZEX = SIZEXSTR == "max" ? std::clamp(MAXSIZE.x, MIN_WINDOW_SIZE, PMONITOR->vecSize.x) : stringToPercentage(SIZEXSTR, PMONITOR->vecSize.x);
|
||||
const auto MAXSIZE = PWINDOW->requestedMaxSize();
|
||||
|
||||
const float SIZEY = SIZEYSTR == "max" ? std::clamp(MAXSIZE.y, MIN_WINDOW_SIZE, PMONITOR->vecSize.y) : stringToPercentage(SIZEYSTR, PMONITOR->vecSize.y);
|
||||
const float SIZEX = SIZEXSTR == "max" ? std::clamp(MAXSIZE.x, MIN_WINDOW_SIZE, PMONITOR->vecSize.x) : stringToPercentage(SIZEXSTR, PMONITOR->vecSize.x);
|
||||
|
||||
Debug::log(LOG, "Rule size (tiled), applying to {}", PWINDOW);
|
||||
const float SIZEY = SIZEYSTR == "max" ? std::clamp(MAXSIZE.y, MIN_WINDOW_SIZE, PMONITOR->vecSize.y) : stringToPercentage(SIZEYSTR, PMONITOR->vecSize.y);
|
||||
|
||||
setPseudo = true;
|
||||
PWINDOW->m_vPseudoSize = Vector2D(SIZEX, SIZEY);
|
||||
Debug::log(LOG, "Rule size (tiled), applying to {}", PWINDOW);
|
||||
|
||||
PWINDOW->setHidden(false);
|
||||
} catch (...) { Debug::log(LOG, "Rule size failed, rule: {} -> {}", r.szRule, r.szValue); }
|
||||
}
|
||||
setPseudo = true;
|
||||
PWINDOW->m_vPseudoSize = Vector2D(SIZEX, SIZEY);
|
||||
|
||||
PWINDOW->setHidden(false);
|
||||
} catch (...) { Debug::log(LOG, "Rule size failed, rule: {} -> {}", r->szRule, r->szValue); }
|
||||
}
|
||||
|
||||
if (!setPseudo)
|
||||
@@ -509,7 +547,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
else if (*PNEWTAKESOVERFS == 1)
|
||||
requestedInternalFSMode = PWINDOW->m_pWorkspace->m_efFullscreenMode;
|
||||
else if (*PNEWTAKESOVERFS == 2)
|
||||
g_pCompositor->setWindowFullscreenInternal(g_pCompositor->getFullscreenWindowOnWorkspace(PWINDOW->m_pWorkspace->m_iID), FSMODE_NONE);
|
||||
g_pCompositor->setWindowFullscreenInternal(PWINDOW->m_pWorkspace->getFullscreenWindow(), FSMODE_NONE);
|
||||
}
|
||||
|
||||
if (!PWINDOW->m_sWindowData.noFocus.valueOrDefault() && !PWINDOW->m_bNoInitialFocus &&
|
||||
@@ -531,7 +569,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
if (!PWINDOW->m_bNoInitialFocus && (requestedInternalFSMode.has_value() || requestedClientFSMode.has_value() || requestedFSState.has_value())) {
|
||||
// fix fullscreen on requested (basically do a switcheroo)
|
||||
if (PWINDOW->m_pWorkspace->m_bHasFullscreenWindow)
|
||||
g_pCompositor->setWindowFullscreenInternal(g_pCompositor->getFullscreenWindowOnWorkspace(PWINDOW->m_pWorkspace->m_iID), FSMODE_NONE);
|
||||
g_pCompositor->setWindowFullscreenInternal(PWINDOW->m_pWorkspace->getFullscreenWindow(), FSMODE_NONE);
|
||||
|
||||
PWINDOW->m_vRealPosition.warp();
|
||||
PWINDOW->m_vRealSize.warp();
|
||||
@@ -539,7 +577,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
PWINDOW->m_sWindowData.syncFullscreen = CWindowOverridableVar(false, PRIORITY_WINDOW_RULE);
|
||||
g_pCompositor->setWindowFullscreenState(PWINDOW, requestedFSState.value());
|
||||
} else if (requestedInternalFSMode.has_value() && requestedClientFSMode.has_value() && !PWINDOW->m_sWindowData.syncFullscreen.valueOrDefault())
|
||||
g_pCompositor->setWindowFullscreenState(PWINDOW, sFullscreenState{.internal = requestedInternalFSMode.value(), .client = requestedClientFSMode.value()});
|
||||
g_pCompositor->setWindowFullscreenState(PWINDOW, SFullscreenState{.internal = requestedInternalFSMode.value(), .client = requestedClientFSMode.value()});
|
||||
else if (requestedInternalFSMode.has_value())
|
||||
g_pCompositor->setWindowFullscreenInternal(PWINDOW, requestedInternalFSMode.value());
|
||||
else if (requestedClientFSMode.has_value())
|
||||
@@ -603,7 +641,8 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
// fix some xwayland apps that don't behave nicely
|
||||
PWINDOW->m_vReportedSize = PWINDOW->m_vPendingReportedSize;
|
||||
|
||||
g_pCompositor->updateWorkspaceWindows(PWINDOW->workspaceID());
|
||||
if (PWINDOW->m_pWorkspace)
|
||||
PWINDOW->m_pWorkspace->updateWindows();
|
||||
|
||||
if (PMONITOR && PWINDOW->isX11OverrideRedirect())
|
||||
PWINDOW->m_fX11SurfaceScaledBy = PMONITOR->scale;
|
||||
@@ -699,7 +738,7 @@ void Events::listener_unmapWindow(void* owner, void* data) {
|
||||
g_pCompositor->setWindowFullscreenInternal(PWINDOWCANDIDATE, CURRENTFSMODE);
|
||||
}
|
||||
|
||||
if (!PWINDOWCANDIDATE && g_pCompositor->getWindowsOnWorkspace(PWINDOW->workspaceID()) == 0)
|
||||
if (!PWINDOWCANDIDATE && PWINDOW->m_pWorkspace && PWINDOW->m_pWorkspace->getWindows() == 0)
|
||||
g_pInputManager->refocus();
|
||||
|
||||
g_pInputManager->sendMotionEventsToFocused();
|
||||
@@ -729,7 +768,8 @@ void Events::listener_unmapWindow(void* owner, void* data) {
|
||||
g_pInputManager->recheckIdleInhibitorStatus();
|
||||
|
||||
// force report all sizes (QT sometimes has an issue with this)
|
||||
g_pCompositor->forceReportSizesToWindowsOnWorkspace(PWINDOW->workspaceID());
|
||||
if (PWINDOW->m_pWorkspace)
|
||||
PWINDOW->m_pWorkspace->forceReportSizesToWindows();
|
||||
|
||||
// update lastwindow after focus
|
||||
PWINDOW->onUnmap();
|
||||
@@ -753,8 +793,8 @@ void Events::listener_commitWindow(void* owner, void* data) {
|
||||
PWINDOW->m_vReportedSize = PWINDOW->m_vPendingReportedSize; // apply pending size. We pinged, the window ponged.
|
||||
|
||||
if (!PWINDOW->m_bIsX11 && !PWINDOW->isFullscreen() && PWINDOW->m_bIsFloating) {
|
||||
const auto MINSIZE = PWINDOW->m_pXDGSurface->toplevel->current.minSize;
|
||||
const auto MAXSIZE = PWINDOW->m_pXDGSurface->toplevel->current.maxSize;
|
||||
const auto MINSIZE = PWINDOW->m_pXDGSurface->toplevel->layoutMinSize();
|
||||
const auto MAXSIZE = PWINDOW->m_pXDGSurface->toplevel->layoutMaxSize();
|
||||
|
||||
PWINDOW->clampWindowSize(MINSIZE, MAXSIZE > Vector2D{1, 1} ? std::optional<Vector2D>{MAXSIZE} : std::nullopt);
|
||||
g_pHyprRenderer->damageWindow(PWINDOW);
|
||||
|
@@ -2,11 +2,11 @@
|
||||
#include "../managers/AnimationManager.hpp"
|
||||
#include "../config/ConfigManager.hpp"
|
||||
|
||||
CBaseAnimatedVariable::CBaseAnimatedVariable(ANIMATEDVARTYPE type) : m_Type(type) {
|
||||
CBaseAnimatedVariable::CBaseAnimatedVariable(eAnimatedVarType type) : m_Type(type) {
|
||||
; // dummy var
|
||||
}
|
||||
|
||||
void CBaseAnimatedVariable::create(SAnimationPropertyConfig* pAnimConfig, PHLWINDOW pWindow, AVARDAMAGEPOLICY policy) {
|
||||
void CBaseAnimatedVariable::create(SAnimationPropertyConfig* pAnimConfig, PHLWINDOW pWindow, eAVarDamagePolicy policy) {
|
||||
m_eDamagePolicy = policy;
|
||||
m_pConfig = pAnimConfig;
|
||||
m_pWindow = pWindow;
|
||||
@@ -14,7 +14,7 @@ void CBaseAnimatedVariable::create(SAnimationPropertyConfig* pAnimConfig, PHLWIN
|
||||
m_bDummy = false;
|
||||
}
|
||||
|
||||
void CBaseAnimatedVariable::create(SAnimationPropertyConfig* pAnimConfig, PHLLS pLayer, AVARDAMAGEPOLICY policy) {
|
||||
void CBaseAnimatedVariable::create(SAnimationPropertyConfig* pAnimConfig, PHLLS pLayer, eAVarDamagePolicy policy) {
|
||||
m_eDamagePolicy = policy;
|
||||
m_pConfig = pAnimConfig;
|
||||
m_pLayer = pLayer;
|
||||
@@ -22,7 +22,7 @@ void CBaseAnimatedVariable::create(SAnimationPropertyConfig* pAnimConfig, PHLLS
|
||||
m_bDummy = false;
|
||||
}
|
||||
|
||||
void CBaseAnimatedVariable::create(SAnimationPropertyConfig* pAnimConfig, PHLWORKSPACE pWorkspace, AVARDAMAGEPOLICY policy) {
|
||||
void CBaseAnimatedVariable::create(SAnimationPropertyConfig* pAnimConfig, PHLWORKSPACE pWorkspace, eAVarDamagePolicy policy) {
|
||||
m_eDamagePolicy = policy;
|
||||
m_pConfig = pAnimConfig;
|
||||
m_pWorkspace = pWorkspace;
|
||||
@@ -30,7 +30,7 @@ void CBaseAnimatedVariable::create(SAnimationPropertyConfig* pAnimConfig, PHLWOR
|
||||
m_bDummy = false;
|
||||
}
|
||||
|
||||
void CBaseAnimatedVariable::create(SAnimationPropertyConfig* pAnimConfig, AVARDAMAGEPOLICY policy) {
|
||||
void CBaseAnimatedVariable::create(SAnimationPropertyConfig* pAnimConfig, eAVarDamagePolicy policy) {
|
||||
m_eDamagePolicy = policy;
|
||||
m_pConfig = pAnimConfig;
|
||||
|
||||
|
@@ -10,38 +10,39 @@
|
||||
#include "../debug/Log.hpp"
|
||||
#include "../desktop/DesktopTypes.hpp"
|
||||
|
||||
enum ANIMATEDVARTYPE {
|
||||
enum eAnimatedVarType : int8_t {
|
||||
AVARTYPE_INVALID = -1,
|
||||
AVARTYPE_FLOAT,
|
||||
AVARTYPE_VECTOR,
|
||||
AVARTYPE_COLOR
|
||||
};
|
||||
|
||||
// Utility to bind a type with its corresponding ANIMATEDVARTYPE
|
||||
// Utility to bind a type with its corresponding eAnimatedVarType
|
||||
template <class T>
|
||||
struct typeToANIMATEDVARTYPE_t {
|
||||
static constexpr ANIMATEDVARTYPE value = AVARTYPE_INVALID;
|
||||
// NOLINTNEXTLINE(readability-identifier-naming)
|
||||
struct STypeToAnimatedVarType_t {
|
||||
static constexpr eAnimatedVarType value = AVARTYPE_INVALID;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct typeToANIMATEDVARTYPE_t<float> {
|
||||
static constexpr ANIMATEDVARTYPE value = AVARTYPE_FLOAT;
|
||||
struct STypeToAnimatedVarType_t<float> {
|
||||
static constexpr eAnimatedVarType value = AVARTYPE_FLOAT;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct typeToANIMATEDVARTYPE_t<Vector2D> {
|
||||
static constexpr ANIMATEDVARTYPE value = AVARTYPE_VECTOR;
|
||||
struct STypeToAnimatedVarType_t<Vector2D> {
|
||||
static constexpr eAnimatedVarType value = AVARTYPE_VECTOR;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct typeToANIMATEDVARTYPE_t<CColor> {
|
||||
static constexpr ANIMATEDVARTYPE value = AVARTYPE_COLOR;
|
||||
struct STypeToAnimatedVarType_t<CHyprColor> {
|
||||
static constexpr eAnimatedVarType value = AVARTYPE_COLOR;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
inline constexpr ANIMATEDVARTYPE typeToANIMATEDVARTYPE = typeToANIMATEDVARTYPE_t<T>::value;
|
||||
inline constexpr eAnimatedVarType typeToeAnimatedVarType = STypeToAnimatedVarType_t<T>::value;
|
||||
|
||||
enum AVARDAMAGEPOLICY {
|
||||
enum eAVarDamagePolicy : int8_t {
|
||||
AVARDAMAGE_NONE = -1,
|
||||
AVARDAMAGE_ENTIRE = 0,
|
||||
AVARDAMAGE_BORDER,
|
||||
@@ -63,15 +64,15 @@ concept OneOf = (... or std::same_as<T, U>);
|
||||
// This is mainly to get better errors if we put a type that's not supported
|
||||
// Otherwise template errors are ugly
|
||||
template <class T>
|
||||
concept Animable = OneOf<T, Vector2D, float, CColor>;
|
||||
concept Animable = OneOf<T, Vector2D, float, CHyprColor>;
|
||||
|
||||
class CBaseAnimatedVariable {
|
||||
public:
|
||||
CBaseAnimatedVariable(ANIMATEDVARTYPE type);
|
||||
void create(SAnimationPropertyConfig* pAnimConfig, PHLWINDOW pWindow, AVARDAMAGEPOLICY policy);
|
||||
void create(SAnimationPropertyConfig* pAnimConfig, PHLLS pLayer, AVARDAMAGEPOLICY policy);
|
||||
void create(SAnimationPropertyConfig* pAnimConfig, PHLWORKSPACE pWorkspace, AVARDAMAGEPOLICY policy);
|
||||
void create(SAnimationPropertyConfig* pAnimConfig, AVARDAMAGEPOLICY policy);
|
||||
CBaseAnimatedVariable(eAnimatedVarType type);
|
||||
void create(SAnimationPropertyConfig* pAnimConfig, PHLWINDOW pWindow, eAVarDamagePolicy policy);
|
||||
void create(SAnimationPropertyConfig* pAnimConfig, PHLLS pLayer, eAVarDamagePolicy policy);
|
||||
void create(SAnimationPropertyConfig* pAnimConfig, PHLWORKSPACE pWorkspace, eAVarDamagePolicy policy);
|
||||
void create(SAnimationPropertyConfig* pAnimConfig, eAVarDamagePolicy policy);
|
||||
|
||||
CBaseAnimatedVariable(const CBaseAnimatedVariable&) = delete;
|
||||
CBaseAnimatedVariable(CBaseAnimatedVariable&&) = delete;
|
||||
@@ -103,7 +104,7 @@ class CBaseAnimatedVariable {
|
||||
float getCurveValue();
|
||||
|
||||
// checks if an animation is in progress
|
||||
inline bool isBeingAnimated() {
|
||||
bool isBeingAnimated() const {
|
||||
return m_bIsBeingAnimated;
|
||||
}
|
||||
|
||||
@@ -111,7 +112,7 @@ class CBaseAnimatedVariable {
|
||||
if an animation is not running, runs instantly.
|
||||
if "remove" is set to true, will remove the callback when ran. */
|
||||
void setCallbackOnEnd(std::function<void(void* thisptr)> func, bool remove = true) {
|
||||
m_fEndCallback = func;
|
||||
m_fEndCallback = std::move(func);
|
||||
m_bRemoveEndAfterRan = remove;
|
||||
|
||||
if (!isBeingAnimated())
|
||||
@@ -121,14 +122,14 @@ class CBaseAnimatedVariable {
|
||||
/* sets a function to be ran when an animation is started.
|
||||
if "remove" is set to true, will remove the callback when ran. */
|
||||
void setCallbackOnBegin(std::function<void(void* thisptr)> func, bool remove = true) {
|
||||
m_fBeginCallback = func;
|
||||
m_fBeginCallback = std::move(func);
|
||||
m_bRemoveBeginAfterRan = remove;
|
||||
}
|
||||
|
||||
/* Sets the update callback, called every time the value is animated and a step is done
|
||||
Warning: calling unregisterVar/registerVar in this handler will cause UB */
|
||||
void setUpdateCallback(std::function<void(void* thisptr)> func) {
|
||||
m_fUpdateCallback = func;
|
||||
m_fUpdateCallback = std::move(func);
|
||||
}
|
||||
|
||||
/* resets all callbacks. Does not call any. */
|
||||
@@ -157,8 +158,8 @@ class CBaseAnimatedVariable {
|
||||
|
||||
std::chrono::steady_clock::time_point animationBegin;
|
||||
|
||||
AVARDAMAGEPOLICY m_eDamagePolicy = AVARDAMAGE_NONE;
|
||||
ANIMATEDVARTYPE m_Type;
|
||||
eAVarDamagePolicy m_eDamagePolicy = AVARDAMAGE_NONE;
|
||||
eAnimatedVarType m_Type;
|
||||
|
||||
bool m_bRemoveEndAfterRan = true;
|
||||
bool m_bRemoveBeginAfterRan = true;
|
||||
@@ -206,24 +207,26 @@ class CBaseAnimatedVariable {
|
||||
template <Animable VarType>
|
||||
class CAnimatedVariable : public CBaseAnimatedVariable {
|
||||
public:
|
||||
CAnimatedVariable() : CBaseAnimatedVariable(typeToANIMATEDVARTYPE<VarType>) {} // dummy var
|
||||
CAnimatedVariable() : CBaseAnimatedVariable(typeToeAnimatedVarType<VarType>) {
|
||||
;
|
||||
} // dummy var
|
||||
|
||||
void create(const VarType& value, SAnimationPropertyConfig* pAnimConfig, PHLWINDOW pWindow, AVARDAMAGEPOLICY policy) {
|
||||
void create(const VarType& value, SAnimationPropertyConfig* pAnimConfig, PHLWINDOW pWindow, eAVarDamagePolicy policy) {
|
||||
create(pAnimConfig, pWindow, policy);
|
||||
m_Value = value;
|
||||
m_Goal = value;
|
||||
}
|
||||
void create(const VarType& value, SAnimationPropertyConfig* pAnimConfig, PHLLS pLayer, AVARDAMAGEPOLICY policy) {
|
||||
void create(const VarType& value, SAnimationPropertyConfig* pAnimConfig, PHLLS pLayer, eAVarDamagePolicy policy) {
|
||||
create(pAnimConfig, pLayer, policy);
|
||||
m_Value = value;
|
||||
m_Goal = value;
|
||||
}
|
||||
void create(const VarType& value, SAnimationPropertyConfig* pAnimConfig, PHLWORKSPACE pWorkspace, AVARDAMAGEPOLICY policy) {
|
||||
void create(const VarType& value, SAnimationPropertyConfig* pAnimConfig, PHLWORKSPACE pWorkspace, eAVarDamagePolicy policy) {
|
||||
create(pAnimConfig, pWorkspace, policy);
|
||||
m_Value = value;
|
||||
m_Goal = value;
|
||||
}
|
||||
void create(const VarType& value, SAnimationPropertyConfig* pAnimConfig, AVARDAMAGEPOLICY policy) {
|
||||
void create(const VarType& value, SAnimationPropertyConfig* pAnimConfig, eAVarDamagePolicy policy) {
|
||||
create(pAnimConfig, policy);
|
||||
m_Value = value;
|
||||
m_Goal = value;
|
||||
|
@@ -6,24 +6,27 @@
|
||||
#include <algorithm>
|
||||
|
||||
void CBezierCurve::setup(std::vector<Vector2D>* pVec) {
|
||||
m_dPoints.clear();
|
||||
|
||||
const auto BEGIN = std::chrono::high_resolution_clock::now();
|
||||
|
||||
m_dPoints.emplace_back(Vector2D(0, 0));
|
||||
|
||||
for (auto const& p : *pVec) {
|
||||
m_dPoints.push_back(p);
|
||||
// Avoid reallocations by reserving enough memory upfront
|
||||
m_vPoints.resize(pVec->size() + 2);
|
||||
m_vPoints[0] = Vector2D(0, 0); // Start point
|
||||
size_t index = 1; // Start after the first element
|
||||
for (const auto& vec : *pVec) {
|
||||
if (index < m_vPoints.size() - 1) { // Bounds check to ensure safety
|
||||
m_vPoints[index] = vec;
|
||||
++index;
|
||||
}
|
||||
}
|
||||
m_vPoints.back() = Vector2D(1, 1); // End point
|
||||
|
||||
m_dPoints.emplace_back(Vector2D(1, 1));
|
||||
|
||||
RASSERT(m_dPoints.size() == 4, "CBezierCurve only supports cubic beziers! (points num: {})", m_dPoints.size());
|
||||
RASSERT(m_vPoints.size() == 4, "CBezierCurve only supports cubic beziers! (points num: {})", m_vPoints.size());
|
||||
|
||||
// bake BAKEDPOINTS points for faster lookups
|
||||
// T -> X ( / BAKEDPOINTS )
|
||||
for (int i = 0; i < BAKEDPOINTS; ++i) {
|
||||
m_aPointsBaked[i] = Vector2D(getXForT((i + 1) / (float)BAKEDPOINTS), getYForT((i + 1) / (float)BAKEDPOINTS));
|
||||
float const t = (i + 1) / (float)BAKEDPOINTS;
|
||||
m_aPointsBaked[i] = Vector2D(getXForT(t), getYForT(t));
|
||||
}
|
||||
|
||||
const auto ELAPSEDUS = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now() - BEGIN).count() / 1000.f;
|
||||
@@ -40,18 +43,26 @@ void CBezierCurve::setup(std::vector<Vector2D>* pVec) {
|
||||
ELAPSEDUS, ELAPSEDCALCAVG);
|
||||
}
|
||||
|
||||
float CBezierCurve::getYForT(float t) {
|
||||
return 3 * t * pow(1 - t, 2) * m_dPoints[1].y + 3 * pow(t, 2) * (1 - t) * m_dPoints[2].y + pow(t, 3);
|
||||
float CBezierCurve::getXForT(float const& t) const {
|
||||
float t2 = t * t;
|
||||
float t3 = t2 * t;
|
||||
|
||||
return 3 * t * (1 - t) * (1 - t) * m_vPoints[1].x + 3 * t2 * (1 - t) * m_vPoints[2].x + t3 * m_vPoints[3].x;
|
||||
}
|
||||
|
||||
float CBezierCurve::getXForT(float t) {
|
||||
return 3 * t * pow(1 - t, 2) * m_dPoints[1].x + 3 * pow(t, 2) * (1 - t) * m_dPoints[2].x + pow(t, 3);
|
||||
float CBezierCurve::getYForT(float const& t) const {
|
||||
float t2 = t * t;
|
||||
float t3 = t2 * t;
|
||||
|
||||
return 3 * t * (1 - t) * (1 - t) * m_vPoints[1].y + 3 * t2 * (1 - t) * m_vPoints[2].y + t3 * m_vPoints[3].y;
|
||||
}
|
||||
|
||||
// Todo: this probably can be done better and faster
|
||||
float CBezierCurve::getYForPoint(float x) {
|
||||
float CBezierCurve::getYForPoint(float const& x) const {
|
||||
if (x >= 1.f)
|
||||
return 1.f;
|
||||
if (x <= 0.f)
|
||||
return 0.f;
|
||||
|
||||
int index = 0;
|
||||
bool below = true;
|
||||
|
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <deque>
|
||||
#include <vector>
|
||||
#include <array>
|
||||
#include <vector>
|
||||
#include "math/Math.hpp"
|
||||
@@ -16,13 +16,13 @@ class CBezierCurve {
|
||||
// this EXCLUDES the 0,0 and 1,1 points,
|
||||
void setup(std::vector<Vector2D>* points);
|
||||
|
||||
float getYForT(float t);
|
||||
float getXForT(float t);
|
||||
float getYForPoint(float x);
|
||||
float getYForT(float const& t) const;
|
||||
float getXForT(float const& t) const;
|
||||
float getYForPoint(float const& x) const;
|
||||
|
||||
private:
|
||||
// this INCLUDES the 0,0 and 1,1 points.
|
||||
std::deque<Vector2D> m_dPoints;
|
||||
std::vector<Vector2D> m_vPoints;
|
||||
|
||||
std::array<Vector2D, BAKEDPOINTS> m_aPointsBaked;
|
||||
};
|
||||
|
@@ -30,25 +30,27 @@ constexpr LD operator""_TB(const LD BYTES) {
|
||||
return BYTES * 1024 * 1024 * 1024 * 1024;
|
||||
}
|
||||
|
||||
//NOLINTBEGIN
|
||||
template <typename T>
|
||||
using __acceptable_byte_operation_type = typename std::enable_if<std::is_trivially_constructible<T, ULL>::value || std::is_trivially_constructible<T, LD>::value>::type;
|
||||
using internal_hl_acceptable_byte_operation_type = typename std::enable_if<std::is_trivially_constructible<T, ULL>::value || std::is_trivially_constructible<T, LD>::value>::type;
|
||||
|
||||
template <typename X, typename = __acceptable_byte_operation_type<X>>
|
||||
template <typename X, typename = internal_hl_acceptable_byte_operation_type<X>>
|
||||
constexpr X kBtoBytes(const X kB) {
|
||||
return kB * 1024;
|
||||
}
|
||||
template <typename X, typename = __acceptable_byte_operation_type<X>>
|
||||
template <typename X, typename = internal_hl_acceptable_byte_operation_type<X>>
|
||||
constexpr X MBtoBytes(const X MB) {
|
||||
return MB * 1024 * 1024;
|
||||
}
|
||||
template <typename X, typename = __acceptable_byte_operation_type<X>>
|
||||
template <typename X, typename = internal_hl_acceptable_byte_operation_type<X>>
|
||||
constexpr X GBtoBytes(const X GB) {
|
||||
return GB * 1024 * 1024 * 1024;
|
||||
}
|
||||
template <typename X, typename = __acceptable_byte_operation_type<X>>
|
||||
template <typename X, typename = internal_hl_acceptable_byte_operation_type<X>>
|
||||
constexpr X TBtoBytes(const X TB) {
|
||||
return TB * 1024 * 1024 * 1024 * 1024;
|
||||
}
|
||||
//NOLINTEND
|
||||
|
||||
#undef ULL
|
||||
#undef LD
|
@@ -5,22 +5,41 @@
|
||||
#define GREEN(c) ((double)(((c) >> 8) & 0xff) / 255.0)
|
||||
#define BLUE(c) ((double)(((c)) & 0xff) / 255.0)
|
||||
|
||||
CColor::CColor() {}
|
||||
CHyprColor::CHyprColor() = default;
|
||||
|
||||
CColor::CColor(float r, float g, float b, float a) {
|
||||
this->r = r;
|
||||
this->g = g;
|
||||
this->b = b;
|
||||
this->a = a;
|
||||
CHyprColor::CHyprColor(float r_, float g_, float b_, float a_) : r(r_), g(g_), b(b_), a(a_) {
|
||||
okLab = Hyprgraphics::CColor(Hyprgraphics::CColor::SSRGB{r, g, b}).asOkLab();
|
||||
}
|
||||
|
||||
CColor::CColor(uint64_t hex) {
|
||||
this->r = RED(hex);
|
||||
this->g = GREEN(hex);
|
||||
this->b = BLUE(hex);
|
||||
this->a = ALPHA(hex);
|
||||
CHyprColor::CHyprColor(uint64_t hex) : r(RED(hex)), g(GREEN(hex)), b(BLUE(hex)), a(ALPHA(hex)) {
|
||||
okLab = Hyprgraphics::CColor(Hyprgraphics::CColor::SSRGB{r, g, b}).asOkLab();
|
||||
}
|
||||
|
||||
uint32_t CColor::getAsHex() const {
|
||||
CHyprColor::CHyprColor(const Hyprgraphics::CColor& color, float a_) : a(a_) {
|
||||
const auto SRGB = color.asRgb();
|
||||
r = SRGB.r;
|
||||
g = SRGB.g;
|
||||
b = SRGB.b;
|
||||
|
||||
okLab = color.asOkLab();
|
||||
}
|
||||
|
||||
uint32_t CHyprColor::getAsHex() const {
|
||||
return (uint32_t)(a * 255.f) * 0x1000000 + (uint32_t)(r * 255.f) * 0x10000 + (uint32_t)(g * 255.f) * 0x100 + (uint32_t)(b * 255.f) * 0x1;
|
||||
}
|
||||
}
|
||||
|
||||
Hyprgraphics::CColor::SSRGB CHyprColor::asRGB() const {
|
||||
return {r, g, b};
|
||||
}
|
||||
|
||||
Hyprgraphics::CColor::SOkLab CHyprColor::asOkLab() const {
|
||||
return okLab;
|
||||
}
|
||||
|
||||
Hyprgraphics::CColor::SHSL CHyprColor::asHSL() const {
|
||||
return Hyprgraphics::CColor(okLab).asHSL();
|
||||
}
|
||||
|
||||
CHyprColor CHyprColor::stripA() const {
|
||||
return {r, g, b, 1.F};
|
||||
}
|
||||
|
@@ -1,35 +1,47 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <hyprgraphics/color/Color.hpp>
|
||||
#include "../debug/Log.hpp"
|
||||
#include "../macros.hpp"
|
||||
|
||||
class CColor {
|
||||
class CHyprColor {
|
||||
public:
|
||||
CColor();
|
||||
CColor(float r, float g, float b, float a);
|
||||
CColor(uint64_t);
|
||||
|
||||
float r = 0, g = 0, b = 0, a = 1.f;
|
||||
CHyprColor();
|
||||
CHyprColor(float r, float g, float b, float a);
|
||||
CHyprColor(const Hyprgraphics::CColor& col, float a);
|
||||
CHyprColor(uint64_t);
|
||||
|
||||
// AR32
|
||||
uint32_t getAsHex() const;
|
||||
uint32_t getAsHex() const;
|
||||
Hyprgraphics::CColor::SSRGB asRGB() const;
|
||||
Hyprgraphics::CColor::SOkLab asOkLab() const;
|
||||
Hyprgraphics::CColor::SHSL asHSL() const;
|
||||
CHyprColor stripA() const;
|
||||
|
||||
CColor operator-(const CColor& c2) const {
|
||||
return CColor(r - c2.r, g - c2.g, b - c2.b, a - c2.a);
|
||||
//
|
||||
bool operator==(const CHyprColor& c2) const {
|
||||
return c2.r == r && c2.g == g && c2.b == b && c2.a == a;
|
||||
}
|
||||
|
||||
CColor operator+(const CColor& c2) const {
|
||||
return CColor(r + c2.r, g + c2.g, b + c2.b, a + c2.a);
|
||||
// stubs for the AnimationMgr
|
||||
CHyprColor operator-(const CHyprColor& c2) const {
|
||||
RASSERT(false, "CHyprColor: - is a STUB");
|
||||
return {};
|
||||
}
|
||||
|
||||
CColor operator*(const float& v) const {
|
||||
return CColor(r * v, g * v, b * v, a * v);
|
||||
CHyprColor operator+(const CHyprColor& c2) const {
|
||||
RASSERT(false, "CHyprColor: + is a STUB");
|
||||
return {};
|
||||
}
|
||||
|
||||
bool operator==(const CColor& c2) const {
|
||||
return r == c2.r && g == c2.g && b == c2.b && a == c2.a;
|
||||
CHyprColor operator*(const float& c2) const {
|
||||
RASSERT(false, "CHyprColor: * is a STUB");
|
||||
return {};
|
||||
}
|
||||
|
||||
CColor stripA() const {
|
||||
return {r, g, b, 1};
|
||||
}
|
||||
double r = 0, g = 0, b = 0, a = 0;
|
||||
|
||||
private:
|
||||
Hyprgraphics::CColor::SOkLab okLab; // cache for the OkLab representation
|
||||
};
|
||||
|
@@ -231,7 +231,7 @@ inline const std::vector<SPixelFormat> GLES3_FORMATS = {
|
||||
},
|
||||
};
|
||||
|
||||
SHMFormat FormatUtils::drmToShm(DRMFormat drm) {
|
||||
SHMFormat NFormatUtils::drmToShm(DRMFormat drm) {
|
||||
switch (drm) {
|
||||
case DRM_FORMAT_XRGB8888: return WL_SHM_FORMAT_XRGB8888;
|
||||
case DRM_FORMAT_ARGB8888: return WL_SHM_FORMAT_ARGB8888;
|
||||
@@ -241,7 +241,7 @@ SHMFormat FormatUtils::drmToShm(DRMFormat drm) {
|
||||
return drm;
|
||||
}
|
||||
|
||||
DRMFormat FormatUtils::shmToDRM(SHMFormat shm) {
|
||||
DRMFormat NFormatUtils::shmToDRM(SHMFormat shm) {
|
||||
switch (shm) {
|
||||
case WL_SHM_FORMAT_XRGB8888: return DRM_FORMAT_XRGB8888;
|
||||
case WL_SHM_FORMAT_ARGB8888: return DRM_FORMAT_ARGB8888;
|
||||
@@ -251,7 +251,7 @@ DRMFormat FormatUtils::shmToDRM(SHMFormat shm) {
|
||||
return shm;
|
||||
}
|
||||
|
||||
const SPixelFormat* FormatUtils::getPixelFormatFromDRM(DRMFormat drm) {
|
||||
const SPixelFormat* NFormatUtils::getPixelFormatFromDRM(DRMFormat drm) {
|
||||
for (auto const& fmt : GLES3_FORMATS) {
|
||||
if (fmt.drmFormat == drm)
|
||||
return &fmt;
|
||||
@@ -260,7 +260,7 @@ const SPixelFormat* FormatUtils::getPixelFormatFromDRM(DRMFormat drm) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const SPixelFormat* FormatUtils::getPixelFormatFromGL(uint32_t glFormat, uint32_t glType, bool alpha) {
|
||||
const SPixelFormat* NFormatUtils::getPixelFormatFromGL(uint32_t glFormat, uint32_t glType, bool alpha) {
|
||||
for (auto const& fmt : GLES3_FORMATS) {
|
||||
if (fmt.glFormat == (int)glFormat && fmt.glType == (int)glType && fmt.withAlpha == alpha)
|
||||
return &fmt;
|
||||
@@ -269,23 +269,23 @@ const SPixelFormat* FormatUtils::getPixelFormatFromGL(uint32_t glFormat, uint32_
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool FormatUtils::isFormatOpaque(DRMFormat drm) {
|
||||
const auto FMT = FormatUtils::getPixelFormatFromDRM(drm);
|
||||
bool NFormatUtils::isFormatOpaque(DRMFormat drm) {
|
||||
const auto FMT = NFormatUtils::getPixelFormatFromDRM(drm);
|
||||
if (!FMT)
|
||||
return false;
|
||||
|
||||
return !FMT->withAlpha;
|
||||
}
|
||||
|
||||
int FormatUtils::pixelsPerBlock(const SPixelFormat* const fmt) {
|
||||
int NFormatUtils::pixelsPerBlock(const SPixelFormat* const fmt) {
|
||||
return fmt->blockSize.x * fmt->blockSize.y > 0 ? fmt->blockSize.x * fmt->blockSize.y : 1;
|
||||
}
|
||||
|
||||
int FormatUtils::minStride(const SPixelFormat* const fmt, int32_t width) {
|
||||
int NFormatUtils::minStride(const SPixelFormat* const fmt, int32_t width) {
|
||||
return std::ceil((width * fmt->bytesPerBlock) / pixelsPerBlock(fmt));
|
||||
}
|
||||
|
||||
uint32_t FormatUtils::drmFormatToGL(DRMFormat drm) {
|
||||
uint32_t NFormatUtils::drmFormatToGL(DRMFormat drm) {
|
||||
switch (drm) {
|
||||
case DRM_FORMAT_XRGB8888:
|
||||
case DRM_FORMAT_XBGR8888: return GL_RGBA; // doesn't matter, opengl is gucci in this case.
|
||||
@@ -302,7 +302,7 @@ uint32_t FormatUtils::drmFormatToGL(DRMFormat drm) {
|
||||
return GL_RGBA;
|
||||
}
|
||||
|
||||
uint32_t FormatUtils::glFormatToType(uint32_t gl) {
|
||||
uint32_t NFormatUtils::glFormatToType(uint32_t gl) {
|
||||
return gl != GL_RGBA ?
|
||||
#ifdef GLES2
|
||||
GL_UNSIGNED_INT_2_10_10_10_REV_EXT :
|
||||
@@ -312,14 +312,14 @@ uint32_t FormatUtils::glFormatToType(uint32_t gl) {
|
||||
GL_UNSIGNED_BYTE;
|
||||
}
|
||||
|
||||
std::string FormatUtils::drmFormatName(DRMFormat drm) {
|
||||
std::string NFormatUtils::drmFormatName(DRMFormat drm) {
|
||||
auto n = drmGetFormatName(drm);
|
||||
std::string name = n;
|
||||
free(n);
|
||||
return name;
|
||||
}
|
||||
|
||||
std::string FormatUtils::drmModifierName(uint64_t mod) {
|
||||
std::string NFormatUtils::drmModifierName(uint64_t mod) {
|
||||
auto n = drmGetFormatModifierName(mod);
|
||||
std::string name = n;
|
||||
free(n);
|
||||
|
@@ -22,7 +22,7 @@ struct SPixelFormat {
|
||||
|
||||
typedef Aquamarine::SDRMFormat SDRMFormat;
|
||||
|
||||
namespace FormatUtils {
|
||||
namespace NFormatUtils {
|
||||
SHMFormat drmToShm(DRMFormat drm);
|
||||
DRMFormat shmToDRM(SHMFormat shm);
|
||||
|
||||
|
@@ -6,6 +6,7 @@
|
||||
#include <optional>
|
||||
#include <cstring>
|
||||
#include <cmath>
|
||||
#include <filesystem>
|
||||
#include <set>
|
||||
#include <sys/utsname.h>
|
||||
#include <sys/mman.h>
|
||||
@@ -17,7 +18,9 @@
|
||||
#include <execinfo.h>
|
||||
#endif
|
||||
#include <hyprutils/string/String.hpp>
|
||||
#include <hyprutils/os/Process.hpp>
|
||||
using namespace Hyprutils::String;
|
||||
using namespace Hyprutils::OS;
|
||||
|
||||
#if defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
|
||||
#include <sys/sysctl.h>
|
||||
@@ -261,7 +264,7 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) {
|
||||
WORKSPACEID id = next ? g_pCompositor->m_pLastMonitor->activeWorkspaceID() : 0;
|
||||
while (++id < LONG_MAX) {
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(id);
|
||||
if (!invalidWSes.contains(id) && (!PWORKSPACE || g_pCompositor->getWindowsOnWorkspace(id) == 0)) {
|
||||
if (!invalidWSes.contains(id) && (!PWORKSPACE || PWORKSPACE->getWindows() == 0)) {
|
||||
result.id = id;
|
||||
return result;
|
||||
}
|
||||
@@ -583,18 +586,12 @@ float vecToRectDistanceSquared(const Vector2D& vec, const Vector2D& p1, const Ve
|
||||
|
||||
// Execute a shell command and get the output
|
||||
std::string execAndGet(const char* cmd) {
|
||||
std::array<char, 128> buffer;
|
||||
std::string result;
|
||||
using PcloseType = int (*)(FILE*);
|
||||
const std::unique_ptr<FILE, PcloseType> pipe(popen(cmd, "r"), static_cast<PcloseType>(pclose));
|
||||
if (!pipe) {
|
||||
Debug::log(ERR, "execAndGet: failed in 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();
|
||||
}
|
||||
|
||||
void logSystemInfo() {
|
||||
@@ -610,9 +607,26 @@ void logSystemInfo() {
|
||||
Debug::log(NONE, "\n");
|
||||
|
||||
#if defined(__DragonFly__) || defined(__FreeBSD__)
|
||||
const std::string GPUINFO = execAndGet("pciconf -lv | fgrep -A4 vga");
|
||||
const std::string GPUINFO = execAndGet("pciconf -lv | grep -F -A4 vga");
|
||||
#elif defined(__arm__) || defined(__aarch64__)
|
||||
const std::string GPUINFO = execAndGet("cat /proc/device-tree/soc*/gpu*/compatible");
|
||||
std::string GPUINFO;
|
||||
const std::filesystem::path dev_tree = "/proc/device-tree";
|
||||
try {
|
||||
if (std::filesystem::exists(dev_tree) && std::filesystem::is_directory(dev_tree)) {
|
||||
std::for_each(std::filesystem::directory_iterator(dev_tree), std::filesystem::directory_iterator{}, [&](const std::filesystem::directory_entry& entry) {
|
||||
if (std::filesystem::is_directory(entry) && entry.path().filename().string().starts_with("soc")) {
|
||||
std::for_each(std::filesystem::directory_iterator(entry.path()), std::filesystem::directory_iterator{}, [&](const std::filesystem::directory_entry& sub_entry) {
|
||||
if (std::filesystem::is_directory(sub_entry) && sub_entry.path().filename().string().starts_with("gpu")) {
|
||||
std::filesystem::path file_path = sub_entry.path() / "compatible";
|
||||
std::ifstream file(file_path);
|
||||
if (file)
|
||||
GPUINFO.append(std::istreambuf_iterator<char>(file), std::istreambuf_iterator<char>());
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
} catch (...) { GPUINFO = "error"; }
|
||||
#else
|
||||
const std::string GPUINFO = execAndGet("lspci -vnn | grep VGA");
|
||||
#endif
|
||||
@@ -677,44 +691,91 @@ int64_t getPPIDof(int64_t pid) {
|
||||
#endif
|
||||
}
|
||||
|
||||
int64_t configStringToInt(const std::string& VALUE) {
|
||||
std::expected<int64_t, std::string> configStringToInt(const std::string& VALUE) {
|
||||
auto parseHex = [](const std::string& value) -> std::expected<int64_t, std::string> {
|
||||
try {
|
||||
size_t position;
|
||||
auto result = stoll(value, &position, 16);
|
||||
if (position == value.size())
|
||||
return result;
|
||||
} catch (const std::exception&) {}
|
||||
return std::unexpected("invalid hex " + value);
|
||||
};
|
||||
if (VALUE.starts_with("0x")) {
|
||||
// Values with 0x are hex
|
||||
const auto VALUEWITHOUTHEX = VALUE.substr(2);
|
||||
return stol(VALUEWITHOUTHEX, nullptr, 16);
|
||||
return parseHex(VALUE);
|
||||
} else if (VALUE.starts_with("rgba(") && VALUE.ends_with(')')) {
|
||||
const auto VALUEWITHOUTFUNC = VALUE.substr(5, VALUE.length() - 6);
|
||||
const auto VALUEWITHOUTFUNC = trim(VALUE.substr(5, VALUE.length() - 6));
|
||||
|
||||
if (trim(VALUEWITHOUTFUNC).length() != 8) {
|
||||
Debug::log(WARN, "invalid length {} for rgba", VALUEWITHOUTFUNC.length());
|
||||
throw std::invalid_argument("rgba() expects length of 8 characters (4 bytes)");
|
||||
// try doing it the comma way first
|
||||
if (std::count(VALUEWITHOUTFUNC.begin(), VALUEWITHOUTFUNC.end(), ',') == 3) {
|
||||
// cool
|
||||
std::string rolling = VALUEWITHOUTFUNC;
|
||||
auto r = configStringToInt(trim(rolling.substr(0, rolling.find(','))));
|
||||
rolling = rolling.substr(rolling.find(',') + 1);
|
||||
auto g = configStringToInt(trim(rolling.substr(0, rolling.find(','))));
|
||||
rolling = rolling.substr(rolling.find(',') + 1);
|
||||
auto b = configStringToInt(trim(rolling.substr(0, rolling.find(','))));
|
||||
rolling = rolling.substr(rolling.find(',') + 1);
|
||||
uint8_t a = 0;
|
||||
|
||||
if (!r || !g || !b)
|
||||
return std::unexpected("failed parsing " + VALUEWITHOUTFUNC);
|
||||
|
||||
try {
|
||||
a = std::round(std::stof(trim(rolling.substr(0, rolling.find(',')))) * 255.f);
|
||||
} catch (std::exception& e) { return std::unexpected("failed parsing " + VALUEWITHOUTFUNC); }
|
||||
|
||||
return a * (Hyprlang::INT)0x1000000 + *r * (Hyprlang::INT)0x10000 + *g * (Hyprlang::INT)0x100 + *b;
|
||||
} else if (VALUEWITHOUTFUNC.length() == 8) {
|
||||
const auto RGBA = parseHex(VALUEWITHOUTFUNC);
|
||||
|
||||
if (!RGBA)
|
||||
return RGBA;
|
||||
// now we need to RGBA -> ARGB. The config holds ARGB only.
|
||||
return (*RGBA >> 8) + 0x1000000 * (*RGBA & 0xFF);
|
||||
}
|
||||
|
||||
const auto RGBA = std::stol(VALUEWITHOUTFUNC, nullptr, 16);
|
||||
return std::unexpected("rgba() expects length of 8 characters (4 bytes) or 4 comma separated values");
|
||||
|
||||
// now we need to RGBA -> ARGB. The config holds ARGB only.
|
||||
return (RGBA >> 8) + 0x1000000 * (RGBA & 0xFF);
|
||||
} else if (VALUE.starts_with("rgb(") && VALUE.ends_with(')')) {
|
||||
const auto VALUEWITHOUTFUNC = VALUE.substr(4, VALUE.length() - 5);
|
||||
const auto VALUEWITHOUTFUNC = trim(VALUE.substr(4, VALUE.length() - 5));
|
||||
|
||||
if (trim(VALUEWITHOUTFUNC).length() != 6) {
|
||||
Debug::log(WARN, "invalid length {} for rgb", VALUEWITHOUTFUNC.length());
|
||||
throw std::invalid_argument("rgb() expects length of 6 characters (3 bytes)");
|
||||
// try doing it the comma way first
|
||||
if (std::count(VALUEWITHOUTFUNC.begin(), VALUEWITHOUTFUNC.end(), ',') == 2) {
|
||||
// cool
|
||||
std::string rolling = VALUEWITHOUTFUNC;
|
||||
auto r = configStringToInt(trim(rolling.substr(0, rolling.find(','))));
|
||||
rolling = rolling.substr(rolling.find(',') + 1);
|
||||
auto g = configStringToInt(trim(rolling.substr(0, rolling.find(','))));
|
||||
rolling = rolling.substr(rolling.find(',') + 1);
|
||||
auto b = configStringToInt(trim(rolling.substr(0, rolling.find(','))));
|
||||
|
||||
if (!r || !g || !b)
|
||||
return std::unexpected("failed parsing " + VALUEWITHOUTFUNC);
|
||||
|
||||
return (Hyprlang::INT)0xFF000000 + *r * (Hyprlang::INT)0x10000 + *g * (Hyprlang::INT)0x100 + *b;
|
||||
} else if (VALUEWITHOUTFUNC.length() == 6) {
|
||||
auto r = parseHex(VALUEWITHOUTFUNC);
|
||||
return r ? *r + 0xFF000000 : r;
|
||||
}
|
||||
|
||||
const auto RGB = std::stol(VALUEWITHOUTFUNC, nullptr, 16);
|
||||
|
||||
return RGB + 0xFF000000; // 0xFF for opaque
|
||||
return std::unexpected("rgb() expects length of 6 characters (3 bytes) or 3 comma separated values");
|
||||
} else if (VALUE.starts_with("true") || VALUE.starts_with("on") || VALUE.starts_with("yes")) {
|
||||
return 1;
|
||||
} else if (VALUE.starts_with("false") || VALUE.starts_with("off") || VALUE.starts_with("no")) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (VALUE.empty() || !isNumber(VALUE))
|
||||
return 0;
|
||||
if (VALUE.empty() || !isNumber(VALUE, false))
|
||||
return std::unexpected("cannot parse \"" + VALUE + "\" as an int.");
|
||||
|
||||
return std::stoll(VALUE);
|
||||
try {
|
||||
const auto RES = std::stoll(VALUE);
|
||||
return RES;
|
||||
} catch (std::exception& e) { return std::unexpected(std::string{"stoll threw: "} + e.what()); }
|
||||
|
||||
return std::unexpected("parse error");
|
||||
}
|
||||
|
||||
Vector2D configStringToVector2D(const std::string& VALUE) {
|
||||
@@ -869,4 +930,31 @@ float stringToPercentage(const std::string& VALUE, const float REL) {
|
||||
return (std::stof(VALUE.substr(0, VALUE.length() - 1)) * REL) / 100.f;
|
||||
else
|
||||
return std::stof(VALUE);
|
||||
};
|
||||
}
|
||||
|
||||
bool executableExistsInPath(const std::string& exe) {
|
||||
if (!getenv("PATH"))
|
||||
return false;
|
||||
|
||||
static CVarList paths(getenv("PATH"), 0, ':', true);
|
||||
|
||||
for (auto& p : paths) {
|
||||
std::string path = p + std::string{"/"} + exe;
|
||||
std::error_code ec;
|
||||
if (!std::filesystem::exists(path, ec) || ec)
|
||||
continue;
|
||||
|
||||
if (!std::filesystem::is_regular_file(path, ec) || ec)
|
||||
continue;
|
||||
|
||||
auto stat = std::filesystem::status(path, ec);
|
||||
if (ec)
|
||||
continue;
|
||||
|
||||
auto perms = stat.permissions();
|
||||
|
||||
return std::filesystem::perms::none != (perms & std::filesystem::perms::others_exec);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@@ -6,6 +6,7 @@
|
||||
#include "math/Math.hpp"
|
||||
#include <vector>
|
||||
#include <format>
|
||||
#include <expected>
|
||||
#include "../SharedDefs.hpp"
|
||||
#include "../macros.hpp"
|
||||
|
||||
@@ -19,28 +20,29 @@ struct SWorkspaceIDName {
|
||||
std::string name;
|
||||
};
|
||||
|
||||
std::string absolutePath(const std::string&, const std::string&);
|
||||
void addWLSignal(wl_signal*, wl_listener*, void* pOwner, const std::string& ownerString);
|
||||
void removeWLSignal(wl_listener*);
|
||||
std::string escapeJSONStrings(const std::string& str);
|
||||
bool isDirection(const std::string&);
|
||||
bool isDirection(const char&);
|
||||
SWorkspaceIDName getWorkspaceIDNameFromString(const std::string&);
|
||||
std::optional<std::string> cleanCmdForWorkspace(const std::string&, std::string);
|
||||
float vecToRectDistanceSquared(const Vector2D& vec, const Vector2D& p1, const Vector2D& p2);
|
||||
void logSystemInfo();
|
||||
std::string execAndGet(const char*);
|
||||
int64_t getPPIDof(int64_t pid);
|
||||
int64_t configStringToInt(const std::string&);
|
||||
Vector2D configStringToVector2D(const std::string&);
|
||||
std::optional<float> getPlusMinusKeywordResult(std::string in, float relative);
|
||||
double normalizeAngleRad(double ang);
|
||||
std::vector<SCallstackFrameInfo> getBacktrace();
|
||||
void throwError(const std::string& err);
|
||||
bool envEnabled(const std::string& env);
|
||||
int allocateSHMFile(size_t len);
|
||||
bool allocateSHMFilePair(size_t size, int* rw_fd_ptr, int* ro_fd_ptr);
|
||||
float stringToPercentage(const std::string& VALUE, const float REL);
|
||||
std::string absolutePath(const std::string&, const std::string&);
|
||||
void addWLSignal(wl_signal*, wl_listener*, void* pOwner, const std::string& ownerString);
|
||||
void removeWLSignal(wl_listener*);
|
||||
std::string escapeJSONStrings(const std::string& str);
|
||||
bool isDirection(const std::string&);
|
||||
bool isDirection(const char&);
|
||||
SWorkspaceIDName getWorkspaceIDNameFromString(const std::string&);
|
||||
std::optional<std::string> cleanCmdForWorkspace(const std::string&, std::string);
|
||||
float vecToRectDistanceSquared(const Vector2D& vec, const Vector2D& p1, const Vector2D& p2);
|
||||
void logSystemInfo();
|
||||
std::string execAndGet(const char*);
|
||||
int64_t getPPIDof(int64_t pid);
|
||||
std::expected<int64_t, std::string> configStringToInt(const std::string&);
|
||||
Vector2D configStringToVector2D(const std::string&);
|
||||
std::optional<float> getPlusMinusKeywordResult(std::string in, float relative);
|
||||
double normalizeAngleRad(double ang);
|
||||
std::vector<SCallstackFrameInfo> getBacktrace();
|
||||
void throwError(const std::string& err);
|
||||
bool envEnabled(const std::string& env);
|
||||
int allocateSHMFile(size_t len);
|
||||
bool allocateSHMFilePair(size_t size, int* rw_fd_ptr, int* ro_fd_ptr);
|
||||
float stringToPercentage(const std::string& VALUE, const float REL);
|
||||
bool executableExistsInPath(const std::string& exe);
|
||||
|
||||
template <typename... Args>
|
||||
[[deprecated("use std::format instead")]] std::string getFormat(std::format_string<Args...> fmt, Args&&... args) {
|
||||
|
@@ -39,6 +39,7 @@ CMonitor::~CMonitor() {
|
||||
}
|
||||
|
||||
void CMonitor::onConnect(bool noRule) {
|
||||
EMIT_HOOK_EVENT("preMonitorAdded", self.lock());
|
||||
CScopeGuard x = {[]() { g_pCompositor->arrangeMonitors(); }};
|
||||
|
||||
if (output->supportsExplicit) {
|
||||
@@ -238,6 +239,7 @@ void CMonitor::onConnect(bool noRule) {
|
||||
}
|
||||
|
||||
void CMonitor::onDisconnect(bool destroy) {
|
||||
EMIT_HOOK_EVENT("preMonitorRemoved", self.lock());
|
||||
CScopeGuard x = {[this]() {
|
||||
if (g_pCompositor->m_bIsShuttingDown)
|
||||
return;
|
||||
@@ -312,7 +314,7 @@ void CMonitor::onDisconnect(bool destroy) {
|
||||
g_pCompositor->warpCursorTo(BACKUPMON->vecPosition + BACKUPMON->vecTransformedSize / 2.F, true);
|
||||
|
||||
// move workspaces
|
||||
std::deque<PHLWORKSPACE> wspToMove;
|
||||
std::vector<PHLWORKSPACE> wspToMove;
|
||||
for (auto const& w : g_pCompositor->m_vWorkspaces) {
|
||||
if (w->m_pMonitor == self || !w->m_pMonitor)
|
||||
wspToMove.push_back(w);
|
||||
@@ -539,7 +541,7 @@ void CMonitor::setMirror(const std::string& mirrorOf) {
|
||||
}
|
||||
|
||||
// move all the WS
|
||||
std::deque<PHLWORKSPACE> wspToMove;
|
||||
std::vector<PHLWORKSPACE> wspToMove;
|
||||
for (auto const& w : g_pCompositor->m_vWorkspaces) {
|
||||
if (w->m_pMonitor == self || !w->m_pMonitor)
|
||||
wspToMove.push_back(w);
|
||||
@@ -627,17 +629,17 @@ void CMonitor::changeWorkspace(const PHLWORKSPACE& pWorkspace, bool internal, bo
|
||||
if (!noFocus && !g_pCompositor->m_pLastMonitor->activeSpecialWorkspace &&
|
||||
!(g_pCompositor->m_pLastWindow.lock() && g_pCompositor->m_pLastWindow->m_bPinned && g_pCompositor->m_pLastWindow->m_pMonitor == self)) {
|
||||
static auto PFOLLOWMOUSE = CConfigValue<Hyprlang::INT>("input:follow_mouse");
|
||||
auto pWindow = pWorkspace->getLastFocusedWindow();
|
||||
auto pWindow = pWorkspace->m_bHasFullscreenWindow ? pWorkspace->getFullscreenWindow() : pWorkspace->getLastFocusedWindow();
|
||||
|
||||
if (!pWindow) {
|
||||
if (*PFOLLOWMOUSE == 1)
|
||||
pWindow = g_pCompositor->vectorToWindowUnified(g_pInputManager->getMouseCoordsInternal(), RESERVED_EXTENTS | INPUT_EXTENTS | ALLOW_FLOATING);
|
||||
|
||||
if (!pWindow)
|
||||
pWindow = g_pCompositor->getTopLeftWindowOnWorkspace(pWorkspace->m_iID);
|
||||
pWindow = pWorkspace->getTopLeftWindow();
|
||||
|
||||
if (!pWindow)
|
||||
pWindow = g_pCompositor->getFirstWindowOnWorkspace(pWorkspace->m_iID);
|
||||
pWindow = pWorkspace->getFirstWindow();
|
||||
}
|
||||
|
||||
g_pCompositor->focusWindow(pWindow);
|
||||
@@ -1008,8 +1010,8 @@ void CMonitor::onMonitorFrame() {
|
||||
g_pHyprRenderer->renderMonitor(self.lock());
|
||||
}
|
||||
|
||||
CMonitorState::CMonitorState(CMonitor* owner) {
|
||||
m_pOwner = owner;
|
||||
CMonitorState::CMonitorState(CMonitor* owner) : m_pOwner(owner) {
|
||||
;
|
||||
}
|
||||
|
||||
CMonitorState::~CMonitorState() {
|
||||
|
@@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "../defines.hpp"
|
||||
#include <deque>
|
||||
#include <vector>
|
||||
#include "WLClasses.hpp"
|
||||
#include <vector>
|
||||
#include <array>
|
||||
@@ -16,7 +16,7 @@
|
||||
#include <aquamarine/allocator/Swapchain.hpp>
|
||||
|
||||
// Enum for the different types of auto directions, e.g. auto-left, auto-up.
|
||||
enum eAutoDirs {
|
||||
enum eAutoDirs : uint8_t {
|
||||
DIR_AUTO_NONE = 0, /* None will be treated as right. */
|
||||
DIR_AUTO_UP,
|
||||
DIR_AUTO_DOWN,
|
||||
|
@@ -4,59 +4,56 @@
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <cerrno>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
namespace Systemd {
|
||||
int SdBooted(void) {
|
||||
if (!faccessat(AT_FDCWD, "/run/systemd/system/", F_OK, AT_SYMLINK_NOFOLLOW))
|
||||
return true;
|
||||
int NSystemd::sdBooted() {
|
||||
if (!faccessat(AT_FDCWD, "/run/systemd/system/", F_OK, AT_SYMLINK_NOFOLLOW))
|
||||
return true;
|
||||
|
||||
if (errno == ENOENT)
|
||||
return false;
|
||||
if (errno == ENOENT)
|
||||
return false;
|
||||
|
||||
return -errno;
|
||||
}
|
||||
|
||||
int SdNotify(int unsetEnvironment, const char* state) {
|
||||
int fd = socket(AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0);
|
||||
if (fd < 0)
|
||||
return -errno;
|
||||
|
||||
constexpr char envVar[] = "NOTIFY_SOCKET";
|
||||
|
||||
auto cleanup = [unsetEnvironment, envVar](int* fd) {
|
||||
if (unsetEnvironment)
|
||||
unsetenv(envVar);
|
||||
close(*fd);
|
||||
};
|
||||
std::unique_ptr<int, decltype(cleanup)> fdCleaup(&fd, cleanup);
|
||||
|
||||
const char* addr = getenv(envVar);
|
||||
if (!addr)
|
||||
return 0;
|
||||
|
||||
// address length must be at most this; see man 7 unix
|
||||
size_t addrLen = strnlen(addr, 107);
|
||||
|
||||
struct sockaddr_un unixAddr;
|
||||
unixAddr.sun_family = AF_UNIX;
|
||||
strncpy(unixAddr.sun_path, addr, addrLen);
|
||||
if (unixAddr.sun_path[0] == '@')
|
||||
unixAddr.sun_path[0] = '\0';
|
||||
|
||||
if (connect(fd, (const sockaddr*)&unixAddr, sizeof(struct sockaddr_un)) < 0)
|
||||
return -errno;
|
||||
|
||||
// arbitrary value which seems to be enough for s-d messages
|
||||
ssize_t stateLen = strnlen(state, 128);
|
||||
if (write(fd, state, stateLen) == stateLen)
|
||||
return 1;
|
||||
|
||||
return -errno;
|
||||
}
|
||||
return -errno;
|
||||
}
|
||||
|
||||
int NSystemd::sdNotify(int unsetEnvironment, const char* state) {
|
||||
int fd = socket(AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0);
|
||||
if (fd < 0)
|
||||
return -errno;
|
||||
|
||||
constexpr char envVar[] = "NOTIFY_SOCKET";
|
||||
|
||||
auto cleanup = [unsetEnvironment, envVar](const int* fd) {
|
||||
if (unsetEnvironment)
|
||||
unsetenv(envVar);
|
||||
close(*fd);
|
||||
};
|
||||
std::unique_ptr<int, decltype(cleanup)> fdCleaup(&fd, cleanup);
|
||||
|
||||
const char* addr = getenv(envVar);
|
||||
if (!addr)
|
||||
return 0;
|
||||
|
||||
// address length must be at most this; see man 7 unix
|
||||
size_t addrLen = strnlen(addr, 107);
|
||||
|
||||
struct sockaddr_un unixAddr;
|
||||
unixAddr.sun_family = AF_UNIX;
|
||||
strncpy(unixAddr.sun_path, addr, addrLen);
|
||||
if (unixAddr.sun_path[0] == '@')
|
||||
unixAddr.sun_path[0] = '\0';
|
||||
|
||||
if (connect(fd, (const sockaddr*)&unixAddr, sizeof(struct sockaddr_un)) < 0)
|
||||
return -errno;
|
||||
|
||||
// arbitrary value which seems to be enough for s-d messages
|
||||
ssize_t stateLen = strnlen(state, 128);
|
||||
if (write(fd, state, stateLen) == stateLen)
|
||||
return 1;
|
||||
|
||||
return -errno;
|
||||
}
|
||||
|
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
namespace Systemd {
|
||||
int SdBooted(void);
|
||||
int SdNotify(int unset_environment, const char* state);
|
||||
namespace NSystemd {
|
||||
int sdBooted(void);
|
||||
int sdNotify(int unset_environment, const char* state);
|
||||
}
|
||||
|
@@ -3,80 +3,135 @@
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
inline const std::vector<std::string> SPLASHES = {
|
||||
// clang-format off
|
||||
"Woo, animations!",
|
||||
"It's like Hypr, but better.",
|
||||
"Release 1.0 when?",
|
||||
"It's not awesome, it's Hyprland!",
|
||||
"\"I commit too often, people can't catch up lmao\" - Vaxry",
|
||||
"This text is random.",
|
||||
"\"There are reasons to not use rust.\" - Boga",
|
||||
"Read the wiki.",
|
||||
"\"Hello everyone this is YOUR daily dose of ‘read the wiki’\" - Vaxry",
|
||||
"h",
|
||||
"\"‘why no work’, bro I haven't hacked your pc to get live feeds yet\" - Vaxry",
|
||||
"Compile, wait for 20 minutes, notice a new commit, compile again.",
|
||||
"To rice, or not to rice, that is the question.",
|
||||
"Now available on Fedora!",
|
||||
"\"Hyprland is so good it starts with a capital letter\" - Hazel",
|
||||
"\"please make this message a splash\" - eriedaberrie",
|
||||
"\"the only wayland compositor powered by fried chicken\" - raf",
|
||||
"\"This will never get into Hyprland\" - Flafy",
|
||||
"\"Hyprland only gives you up on -git\" - fazzi",
|
||||
"Segmentation fault (core dumped)",
|
||||
"\"disabling hyprland logo is a war crime\" - vaxry",
|
||||
"some basic startup code",
|
||||
"\"I think I am addicted to hyprland\" - mathisbuilder",
|
||||
"\"hyprland is the most important package in the arch repos\" - jacekpoz",
|
||||
"Thanks Brodie!",
|
||||
"Thanks fufexan!",
|
||||
"Thanks raf!",
|
||||
"You can't use --splash to change this message :)",
|
||||
"Hyprland will overtake Gnome in popularity by [insert year]",
|
||||
// music reference / quote section
|
||||
"J'remue le ciel, le jour, la nuit.",
|
||||
"aezakmi, aezakmi, aezakmi, aezakmi, aezakmi, aezakmi, aezakmi!",
|
||||
"Wir sind schon sehr lang zusammen...",
|
||||
"I see a red door and I want it painted black.",
|
||||
"Take on me, take me on...",
|
||||
"You spin me right round baby right round",
|
||||
"Stayin' alive, stayin' alive",
|
||||
"Say no way, say no way ya, no way!",
|
||||
"Ground control to Major Tom...",
|
||||
"Alors on danse",
|
||||
"And all that I can see, is just a yellow lemon tree.",
|
||||
"Got a one-way ticket to the blues",
|
||||
"Is this the real life, is this just fantasy",
|
||||
"What's in your head, in your head?",
|
||||
"We're all living in America, America, America.",
|
||||
"I'm still standing, better than I ever did",
|
||||
"Here comes the sun, bringing you love and shining on everyone",
|
||||
"Two trailer park girls go round the outside",
|
||||
"With the lights out, it's less dangerous",
|
||||
"Here we go back, this is the moment, tonight is the night",
|
||||
"Now you're just somebody that I used to know...",
|
||||
"Black bird, black moon, black sky",
|
||||
"Some legends are told, some turn to dust or to gold",
|
||||
"Your brain gets smart, but your head gets dumb.",
|
||||
"Save your mercy for someone who needs it more",
|
||||
"You're gonna hear my voice when I shout it out loud",
|
||||
"Ding ding pch n daa, bam-ba-ba-re-bam baram bom bom baba-bam-bam-bommm",
|
||||
"Súbeme la radio que esta es mi canción",
|
||||
"I'm beggin', beggin' you",
|
||||
"Never gonna let you down (I am trying!)",
|
||||
"\"I use Arch, btw\" - John Cena",
|
||||
"\"Hyper\".replace(\"e\", \"\")",
|
||||
"\"my win11 install runs hyprland that is true\" - raf",
|
||||
"\"stop playing league loser\" - hyprBot",
|
||||
"\"If it ain't broke, don't fix it\" - Lucascito_03",
|
||||
"\"@vaxry how do i learn c++\" - flicko",
|
||||
//
|
||||
"Join the discord server!",
|
||||
"Thanks ThatOneCalculator!",
|
||||
"The AUR packages always work, except for the times they don't.",
|
||||
"Funny animation compositor woo",
|
||||
//
|
||||
"2 years!"
|
||||
// clang-format on
|
||||
namespace NSplashes {
|
||||
inline const std::vector<std::string> SPLASHES = {
|
||||
// clang-format off
|
||||
"Woo, animations!",
|
||||
"It's like Hypr, but better.",
|
||||
"Release 1.0 when?",
|
||||
"It's not awesome, it's Hyprland!",
|
||||
"\"I commit too often, people can't catch up lmao\" - Vaxry",
|
||||
"This text is random.",
|
||||
"\"There are reasons to not use rust.\" - Boga",
|
||||
"Read the wiki.",
|
||||
"\"Hello everyone this is YOUR daily dose of ‘read the wiki’\" - Vaxry",
|
||||
"h",
|
||||
"\"‘why no work’, bro I haven't hacked your pc to get live feeds yet\" - Vaxry",
|
||||
"Compile, wait for 20 minutes, notice a new commit, compile again.",
|
||||
"To rice, or not to rice, that is the question.",
|
||||
"Now available on Fedora!",
|
||||
"\"Hyprland is so good it starts with a capital letter\" - Hazel",
|
||||
"\"please make this message a splash\" - eriedaberrie",
|
||||
"\"the only wayland compositor powered by fried chicken\" - raf",
|
||||
"\"This will never get into Hyprland\" - Flafy",
|
||||
"\"Hyprland only gives you up on -git\" - fazzi",
|
||||
"Segmentation fault (core dumped)",
|
||||
"\"disabling hyprland logo is a war crime\" - vaxry",
|
||||
"some basic startup code",
|
||||
"\"I think I am addicted to hyprland\" - mathisbuilder",
|
||||
"\"hyprland is the most important package in the arch repos\" - jacekpoz",
|
||||
"Thanks Brodie!",
|
||||
"Thanks fufexan!",
|
||||
"Thanks raf!",
|
||||
"You can't use --splash to change this message :)",
|
||||
"Hyprland will overtake Gnome in popularity by [insert year]",
|
||||
"Designed in California - Assembled in China",
|
||||
"\"something <time here> and still no new splash\" - snowman",
|
||||
"My name is Land. Hypr Land. One red bull, shaken not stirred.",
|
||||
"\"Glory To The Emperor\" - raf",
|
||||
"Help I forgot to install kitty",
|
||||
"Go to settings to activate Hyprland",
|
||||
"Why is there code??? Make a damn .exe file and give it to me.",
|
||||
"Hyprland is not a window manager!",
|
||||
"Can we get a version without anime girls?",
|
||||
"Check out quickshell!",
|
||||
"A day without Hyprland is a day wasted",
|
||||
"By dt, do you mean damage tracking or distrotube?",
|
||||
"Made in Poland",
|
||||
"\"I use Arch, btw\" - John Cena",
|
||||
"\"Hyper\".replace(\"e\", \"\")",
|
||||
"\"my win11 install runs hyprland that is true\" - raf",
|
||||
"\"stop playing league loser\" - hyprBot",
|
||||
"\"If it ain't broke, don't fix it\" - Lucascito_03",
|
||||
"\"@vaxry how do i learn c++\" - flicko",
|
||||
"Join the discord server!",
|
||||
"Thanks ThatOneCalculator!",
|
||||
"The AUR packages always work, except for the times they don't.",
|
||||
"Funny animation compositor woo",
|
||||
"2 years!",
|
||||
// music reference / quote section
|
||||
"J'remue le ciel, le jour, la nuit.",
|
||||
"aezakmi, aezakmi, aezakmi, aezakmi, aezakmi, aezakmi, aezakmi!",
|
||||
"Wir sind schon sehr lang zusammen...",
|
||||
"I see a red door and I want it painted black.",
|
||||
"Take on me, take me on...",
|
||||
"You spin me right round baby right round",
|
||||
"Stayin' alive, stayin' alive",
|
||||
"Say no way, say no way ya, no way!",
|
||||
"Ground control to Major Tom...",
|
||||
"Alors on danse",
|
||||
"And all that I can see, is just a yellow lemon tree.",
|
||||
"Got a one-way ticket to the blues",
|
||||
"Is this the real life, is this just fantasy",
|
||||
"What's in your head, in your head?",
|
||||
"We're all living in America, America, America.",
|
||||
"I'm still standing, better than I ever did",
|
||||
"Here comes the sun, bringing you love and shining on everyone",
|
||||
"Two trailer park girls go round the outside",
|
||||
"With the lights out, it's less dangerous",
|
||||
"Here we go back, this is the moment, tonight is the night",
|
||||
"Now you're just somebody that I used to know...",
|
||||
"Black bird, black moon, black sky",
|
||||
"Some legends are told, some turn to dust or to gold",
|
||||
"Your brain gets smart, but your head gets dumb.",
|
||||
"Save your mercy for someone who needs it more",
|
||||
"You're gonna hear my voice when I shout it out loud",
|
||||
"Ding ding pch n daa, bam-ba-ba-re-bam baram bom bom baba-bam-bam-bommm",
|
||||
"Súbeme la radio que esta es mi canción",
|
||||
"I'm beggin', beggin' you",
|
||||
"Never gonna let you down (I am trying!)",
|
||||
"Hier kommt die Sonne",
|
||||
"Kickstart my heart, give it a start",
|
||||
"Fear of the dark, I have a constant fear that something's always near",
|
||||
"Komm mit, reih dich ein.",
|
||||
"I wish I had an angel for one moment of love",
|
||||
"We're the children of the dark",
|
||||
"You float like a feather, in a beautiful world",
|
||||
"Demons come at night and they bring the end",
|
||||
"All I wanna say is that they don't really care about us",
|
||||
"Has he lost his mind? Can he see or is he blind?",
|
||||
// clang-format on
|
||||
};
|
||||
|
||||
inline const std::vector<std::string> SPLASHES_CHRISTMAS = {
|
||||
// clang-format off
|
||||
"Merry Christmas!",
|
||||
"Merry Xmas!",
|
||||
"Ho ho ho",
|
||||
"Santa was here",
|
||||
"Make sure to spend some jolly time with those near and dear to you!",
|
||||
"Have you checked for christmas presents yet?",
|
||||
// clang-format on
|
||||
};
|
||||
|
||||
// ONLY valid near new years.
|
||||
inline static int newYear = []() -> int {
|
||||
auto tt = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
|
||||
auto local = *localtime(&tt);
|
||||
|
||||
if (local.tm_mon < 8 /* decided with a fair die I promise. */)
|
||||
return local.tm_year + 1900;
|
||||
return local.tm_year + 1901;
|
||||
}();
|
||||
|
||||
inline const std::vector<std::string> SPLASHES_NEWYEAR = {
|
||||
// clang-format off
|
||||
"Happy new Year!",
|
||||
"[New year] will be the year of the Linux desktop!",
|
||||
"[New year] will be the year of the Hyprland desktop!",
|
||||
std::format("{} will be the year of the Linux desktop!", newYear),
|
||||
std::format("{} will be the year of the Hyprland desktop!", newYear),
|
||||
std::format("Let's make {} even better than {}!", newYear, newYear - 1),
|
||||
// clang-format on
|
||||
};
|
||||
};
|
@@ -5,11 +5,11 @@
|
||||
|
||||
class CTagKeeper {
|
||||
public:
|
||||
bool isTagged(const std::string& tag, bool strict = false);
|
||||
bool applyTag(const std::string& tag, bool dynamic = false);
|
||||
bool removeDynamicTags();
|
||||
bool isTagged(const std::string& tag, bool strict = false);
|
||||
bool applyTag(const std::string& tag, bool dynamic = false);
|
||||
bool removeDynamicTags();
|
||||
|
||||
inline const auto& getTags() {
|
||||
const auto& getTags() const {
|
||||
return m_tags;
|
||||
};
|
||||
|
||||
|
@@ -1,5 +1,5 @@
|
||||
#include "Watchdog.hpp"
|
||||
#include <signal.h>
|
||||
#include <csignal>
|
||||
#include "config/ConfigManager.hpp"
|
||||
#include "../config/ConfigValue.hpp"
|
||||
|
||||
@@ -12,8 +12,7 @@ CWatchdog::~CWatchdog() {
|
||||
m_pWatchdog->join();
|
||||
}
|
||||
|
||||
CWatchdog::CWatchdog() {
|
||||
m_iMainThreadPID = pthread_self();
|
||||
CWatchdog::CWatchdog() : m_iMainThreadPID(pthread_self()) {
|
||||
|
||||
m_pWatchdog = std::make_unique<std::thread>([this] {
|
||||
static auto PTIMEOUT = CConfigValue<Hyprlang::INT>("debug:watchdog_timeout");
|
||||
@@ -24,7 +23,7 @@ CWatchdog::CWatchdog() {
|
||||
|
||||
if (!m_bWillWatch)
|
||||
m_cvWatchdogCondition.wait(lk, [this] { return m_bNotified || m_bExitThread; });
|
||||
else if (m_cvWatchdogCondition.wait_for(lk, std::chrono::milliseconds((int)(*PTIMEOUT * 1000.0)), [this] { return m_bNotified || m_bExitThread; }) == false)
|
||||
else if (!m_cvWatchdogCondition.wait_for(lk, std::chrono::milliseconds((int)(*PTIMEOUT * 1000.0)), [this] { return m_bNotified || m_bExitThread; }))
|
||||
pthread_kill(m_iMainThreadPID, SIGUSR1);
|
||||
|
||||
if (m_bExitThread)
|
||||
|
@@ -6,6 +6,7 @@
|
||||
#include <hyprutils/math/Region.hpp>
|
||||
#include <hyprutils/math/Mat3x3.hpp>
|
||||
|
||||
// NOLINTNEXTLINE
|
||||
using namespace Hyprutils::Math;
|
||||
|
||||
eTransform wlTransformToHyprutils(wl_output_transform t);
|
||||
|
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <hyprutils/memory/WeakPtr.hpp>
|
||||
|
||||
//NOLINTNEXTLINE
|
||||
using namespace Hyprutils::Memory;
|
||||
|
||||
#define SP Hyprutils::Memory::CSharedPointer
|
||||
|
@@ -2,4 +2,5 @@
|
||||
|
||||
#include <hyprutils/signal/Signal.hpp>
|
||||
|
||||
//NOLINTNEXTLINE
|
||||
using namespace Hyprutils::Signal;
|
||||
|
@@ -2,4 +2,5 @@
|
||||
|
||||
#include <hyprutils/string/VarList.hpp>
|
||||
|
||||
//NOLINTNEXTLINE
|
||||
using namespace Hyprutils::String;
|
||||
|
@@ -33,7 +33,7 @@ CHyprError::~CHyprError() {
|
||||
m_fFadeOpacity.unregister();
|
||||
}
|
||||
|
||||
void CHyprError::queueCreate(std::string message, const CColor& color) {
|
||||
void CHyprError::queueCreate(std::string message, const CHyprColor& color) {
|
||||
m_szQueued = message;
|
||||
m_cQueued = color;
|
||||
}
|
||||
@@ -98,7 +98,7 @@ void CHyprError::createQueued() {
|
||||
cairo_stroke(CAIRO);
|
||||
|
||||
// draw the text with a common font
|
||||
const CColor textColor = CColor(0.9, 0.9, 0.9, 1.0);
|
||||
const CHyprColor textColor = CHyprColor(0.9, 0.9, 0.9, 1.0);
|
||||
cairo_set_source_rgba(CAIRO, textColor.r, textColor.g, textColor.b, textColor.a);
|
||||
|
||||
static auto fontFamily = CConfigValue<std::string>("misc:font_family");
|
||||
@@ -160,7 +160,7 @@ void CHyprError::createQueued() {
|
||||
|
||||
m_bIsCreated = true;
|
||||
m_szQueued = "";
|
||||
m_cQueued = CColor();
|
||||
m_cQueued = CHyprColor();
|
||||
|
||||
g_pHyprRenderer->damageMonitor(PMONITOR);
|
||||
|
||||
|
@@ -11,7 +11,7 @@ class CHyprError {
|
||||
CHyprError();
|
||||
~CHyprError();
|
||||
|
||||
void queueCreate(std::string message, const CColor& color);
|
||||
void queueCreate(std::string message, const CHyprColor& color);
|
||||
void draw();
|
||||
void destroy();
|
||||
|
||||
@@ -21,7 +21,7 @@ class CHyprError {
|
||||
private:
|
||||
void createQueued();
|
||||
std::string m_szQueued = "";
|
||||
CColor m_cQueued;
|
||||
CHyprColor m_cQueued;
|
||||
bool m_bQueuedDestroy = false;
|
||||
bool m_bIsCreated = false;
|
||||
SP<CTexture> m_pTexture;
|
||||
|
@@ -9,11 +9,11 @@
|
||||
#include <getopt.h>
|
||||
#include <libinput.h>
|
||||
#include <linux/input-event-codes.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <csignal>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <sys/wait.h>
|
||||
#include <time.h>
|
||||
#include <ctime>
|
||||
#include <unistd.h>
|
||||
#include <wayland-server-core.h>
|
||||
|
||||
|
@@ -1,10 +1,10 @@
|
||||
#include "initHelpers.hpp"
|
||||
|
||||
bool Init::isSudo() {
|
||||
bool NInit::isSudo() {
|
||||
return getuid() != geteuid() || !geteuid();
|
||||
}
|
||||
|
||||
void Init::gainRealTime() {
|
||||
void NInit::gainRealTime() {
|
||||
const int minPrio = sched_get_priority_min(SCHED_RR);
|
||||
int old_policy;
|
||||
struct sched_param param;
|
||||
@@ -21,7 +21,7 @@ void Init::gainRealTime() {
|
||||
return;
|
||||
}
|
||||
|
||||
pthread_atfork(NULL, NULL, []() {
|
||||
pthread_atfork(nullptr, nullptr, []() {
|
||||
const struct sched_param param = {.sched_priority = 0};
|
||||
if (pthread_setschedparam(pthread_self(), SCHED_OTHER, ¶m))
|
||||
Debug::log(WARN, "Failed to reset process scheduling strategy");
|
||||
|
@@ -2,7 +2,7 @@
|
||||
|
||||
#include "../defines.hpp"
|
||||
|
||||
namespace Init {
|
||||
namespace NInit {
|
||||
bool isSudo();
|
||||
void gainRealTime();
|
||||
};
|
@@ -12,9 +12,9 @@ void SDwindleNodeData::recalcSizePosRecursive(bool force, bool horizontalOverrid
|
||||
if (*PPRESERVESPLIT == 0 && *PSMARTSPLIT == 0)
|
||||
splitTop = box.h * *PFLMULT > box.w;
|
||||
|
||||
if (verticalOverride == true)
|
||||
if (verticalOverride)
|
||||
splitTop = true;
|
||||
else if (horizontalOverride == true)
|
||||
else if (horizontalOverride)
|
||||
splitTop = false;
|
||||
|
||||
const auto SPLITSIDE = !splitTop;
|
||||
@@ -38,13 +38,12 @@ void SDwindleNodeData::recalcSizePosRecursive(bool force, bool horizontalOverrid
|
||||
}
|
||||
}
|
||||
|
||||
void SDwindleNodeData::getAllChildrenRecursive(std::deque<SDwindleNodeData*>* pDeque) {
|
||||
void SDwindleNodeData::getAllChildrenRecursive(std::vector<SDwindleNodeData*>* pVec) {
|
||||
if (children[0]) {
|
||||
children[0]->getAllChildrenRecursive(pDeque);
|
||||
children[1]->getAllChildrenRecursive(pDeque);
|
||||
} else {
|
||||
pDeque->push_back(this);
|
||||
}
|
||||
children[0]->getAllChildrenRecursive(pVec);
|
||||
children[1]->getAllChildrenRecursive(pVec);
|
||||
} else
|
||||
pVec->push_back(this);
|
||||
}
|
||||
|
||||
int CHyprDwindleLayout::getNodesOnWorkspace(const WORKSPACEID& id) {
|
||||
@@ -231,7 +230,7 @@ void CHyprDwindleLayout::onWindowCreatedTiling(PHLWINDOW pWindow, eDirection dir
|
||||
if (pWindow->m_bIsFloating)
|
||||
return;
|
||||
|
||||
m_lDwindleNodesData.push_back(SDwindleNodeData());
|
||||
m_lDwindleNodesData.emplace_back();
|
||||
const auto PNODE = &m_lDwindleNodesData.back();
|
||||
|
||||
const auto PMONITOR = pWindow->m_pMonitor.lock();
|
||||
@@ -283,7 +282,7 @@ void CHyprDwindleLayout::onWindowCreatedTiling(PHLWINDOW pWindow, eDirection dir
|
||||
|
||||
// first, check if OPENINGON isn't too big.
|
||||
const auto PREDSIZEMAX = OPENINGON ? Vector2D(OPENINGON->box.w, OPENINGON->box.h) : PMONITOR->vecSize;
|
||||
if (const auto MAXSIZE = g_pXWaylandManager->getMaxSizeForWindow(pWindow); MAXSIZE.x < PREDSIZEMAX.x || MAXSIZE.y < PREDSIZEMAX.y) {
|
||||
if (const auto MAXSIZE = pWindow->requestedMaxSize(); MAXSIZE.x < PREDSIZEMAX.x || MAXSIZE.y < PREDSIZEMAX.y) {
|
||||
// we can't continue. make it floating.
|
||||
pWindow->m_bIsFloating = true;
|
||||
m_lDwindleNodesData.remove(*PNODE);
|
||||
@@ -312,7 +311,7 @@ void CHyprDwindleLayout::onWindowCreatedTiling(PHLWINDOW pWindow, eDirection dir
|
||||
|
||||
// get the node under our cursor
|
||||
|
||||
m_lDwindleNodesData.push_back(SDwindleNodeData());
|
||||
m_lDwindleNodesData.emplace_back();
|
||||
const auto NEWPARENT = &m_lDwindleNodesData.back();
|
||||
|
||||
// make the parent have the OPENINGON's stats
|
||||
@@ -514,7 +513,7 @@ void CHyprDwindleLayout::calculateWorkspace(const PHLWORKSPACE& pWorkspace) {
|
||||
|
||||
if (pWorkspace->m_bHasFullscreenWindow) {
|
||||
// massive hack from the fullscreen func
|
||||
const auto PFULLWINDOW = g_pCompositor->getFullscreenWindowOnWorkspace(pWorkspace->m_iID);
|
||||
const auto PFULLWINDOW = pWorkspace->getFullscreenWindow();
|
||||
|
||||
if (pWorkspace->m_efFullscreenMode == FSMODE_FULLSCREEN) {
|
||||
PFULLWINDOW->m_vRealPosition = PMONITOR->vecPosition;
|
||||
@@ -805,14 +804,13 @@ void CHyprDwindleLayout::recalculateWindow(PHLWINDOW pWindow) {
|
||||
PNODE->recalcSizePosRecursive();
|
||||
}
|
||||
|
||||
void addToDequeRecursive(std::deque<SDwindleNodeData*>* pDeque, std::deque<SDwindleNodeData*>* pParents, SDwindleNodeData* node) {
|
||||
static void addToVectorRecursive(std::vector<SDwindleNodeData*>* pVec, std::vector<SDwindleNodeData*>* pParents, SDwindleNodeData* node) {
|
||||
if (node->isNode) {
|
||||
pParents->push_back(node);
|
||||
addToDequeRecursive(pDeque, pParents, node->children[0]);
|
||||
addToDequeRecursive(pDeque, pParents, node->children[1]);
|
||||
} else {
|
||||
pDeque->emplace_back(node);
|
||||
}
|
||||
pParents->emplace_back(node);
|
||||
addToVectorRecursive(pVec, pParents, node->children[0]);
|
||||
addToVectorRecursive(pVec, pParents, node->children[1]);
|
||||
} else
|
||||
pVec->emplace_back(node);
|
||||
}
|
||||
|
||||
SWindowRenderLayoutHints CHyprDwindleLayout::requestRenderHints(PHLWINDOW pWindow) {
|
||||
@@ -1054,7 +1052,7 @@ void CHyprDwindleLayout::moveToRoot(PHLWINDOW pWindow, bool stable) {
|
||||
std::swap(pRoot->children[0], pRoot->children[1]);
|
||||
|
||||
// if the workspace is visible, recalculate layout
|
||||
if (g_pCompositor->isWorkspaceVisible(pWindow->m_pWorkspace))
|
||||
if (pWindow->m_pWorkspace && pWindow->m_pWorkspace->isVisible())
|
||||
pRoot->recalcSizePosRecursive();
|
||||
}
|
||||
|
||||
@@ -1094,7 +1092,7 @@ Vector2D CHyprDwindleLayout::predictSizeForNewWindowTiled() {
|
||||
PHLWINDOW candidate = g_pCompositor->m_pLastWindow.lock();
|
||||
|
||||
if (!candidate)
|
||||
candidate = g_pCompositor->getFirstWindowOnWorkspace(g_pCompositor->m_pLastMonitor->activeWorkspace->m_iID);
|
||||
candidate = g_pCompositor->m_pLastMonitor->activeWorkspace->getFirstWindow();
|
||||
|
||||
// create a fake node
|
||||
SDwindleNodeData node;
|
||||
|
@@ -4,7 +4,7 @@
|
||||
#include "../desktop/DesktopTypes.hpp"
|
||||
|
||||
#include <list>
|
||||
#include <deque>
|
||||
#include <vector>
|
||||
#include <array>
|
||||
#include <optional>
|
||||
#include <format>
|
||||
@@ -39,7 +39,7 @@ struct SDwindleNodeData {
|
||||
}
|
||||
|
||||
void recalcSizePosRecursive(bool force = false, bool horizontalOverride = false, bool verticalOverride = false);
|
||||
void getAllChildrenRecursive(std::deque<SDwindleNodeData*>*);
|
||||
void getAllChildrenRecursive(std::vector<SDwindleNodeData*>*);
|
||||
CHyprDwindleLayout* layout = nullptr;
|
||||
};
|
||||
|
||||
|
@@ -20,9 +20,6 @@ void IHyprLayout::onWindowCreated(PHLWINDOW pWindow, eDirection direction) {
|
||||
|
||||
pWindow->m_vPseudoSize = pWindow->m_vLastFloatingSize;
|
||||
|
||||
if (!g_pXWaylandManager->shouldBeFloated(pWindow)) // do not apply group rules to child windows
|
||||
pWindow->applyGroupRules();
|
||||
|
||||
bool autoGrouped = IHyprLayout::onWindowCreatedAutoGroup(pWindow);
|
||||
if (autoGrouped)
|
||||
return;
|
||||
@@ -31,6 +28,9 @@ void IHyprLayout::onWindowCreated(PHLWINDOW pWindow, eDirection direction) {
|
||||
onWindowCreatedFloating(pWindow);
|
||||
else
|
||||
onWindowCreatedTiling(pWindow, direction);
|
||||
|
||||
if (!g_pXWaylandManager->shouldBeFloated(pWindow)) // do not apply group rules to child windows
|
||||
pWindow->applyGroupRules();
|
||||
}
|
||||
|
||||
void IHyprLayout::onWindowRemoved(PHLWINDOW pWindow) {
|
||||
@@ -81,7 +81,7 @@ void IHyprLayout::onWindowRemoved(PHLWINDOW pWindow) {
|
||||
}
|
||||
|
||||
void IHyprLayout::onWindowRemovedFloating(PHLWINDOW pWindow) {
|
||||
return; // no-op
|
||||
; // no-op
|
||||
}
|
||||
|
||||
void IHyprLayout::onWindowCreatedFloating(PHLWINDOW pWindow) {
|
||||
@@ -187,7 +187,7 @@ bool IHyprLayout::onWindowCreatedAutoGroup(PHLWINDOW pWindow) {
|
||||
static auto PAUTOGROUP = CConfigValue<Hyprlang::INT>("group:auto_group");
|
||||
const PHLWINDOW OPENINGON = g_pCompositor->m_pLastWindow.lock() && g_pCompositor->m_pLastWindow->m_pWorkspace == pWindow->m_pWorkspace ?
|
||||
g_pCompositor->m_pLastWindow.lock() :
|
||||
g_pCompositor->getFirstWindowOnWorkspace(pWindow->workspaceID());
|
||||
(pWindow->m_pWorkspace ? pWindow->m_pWorkspace->getFirstWindow() : nullptr);
|
||||
const bool FLOATEDINTOTILED = pWindow->m_bIsFloating && !OPENINGON->m_bIsFloating;
|
||||
const bool SWALLOWING = pWindow->m_pSwallowed || pWindow->m_bGroupSwallowed;
|
||||
|
||||
@@ -455,7 +455,7 @@ static void performSnap(Vector2D& sourcePos, Vector2D& sourceSize, PHLWINDOW DRA
|
||||
|
||||
// corner snapping
|
||||
const double BORDERDIFF = OTHERBORDERSIZE - DRAGGINGBORDERSIZE;
|
||||
if (sourceX.start == SURFBX.end || SURFBX.start == sourceX.end) {
|
||||
if (snaps & (SNAP_LEFT | SNAP_RIGHT)) {
|
||||
const SRange SURFY = {SURF.y - BORDERDIFF, SURF.y + SURF.h + BORDERDIFF};
|
||||
if (CORNER & (CORNER_TOPLEFT | CORNER_TOPRIGHT) && canSnap(sourceY.start, SURFY.start, GAPSIZE)) {
|
||||
SNAP(sourceY.start, sourceY.end, SURFY.start);
|
||||
@@ -465,7 +465,7 @@ static void performSnap(Vector2D& sourcePos, Vector2D& sourceSize, PHLWINDOW DRA
|
||||
snaps |= SNAP_DOWN;
|
||||
}
|
||||
}
|
||||
if (sourceY.start == SURFBY.end || SURFBY.start == sourceY.end) {
|
||||
if (snaps & (SNAP_UP | SNAP_DOWN)) {
|
||||
const SRange SURFX = {SURF.x - BORDERDIFF, SURF.x + SURF.w + BORDERDIFF};
|
||||
if (CORNER & (CORNER_TOPLEFT | CORNER_BOTTOMLEFT) && canSnap(sourceX.start, SURFX.start, GAPSIZE)) {
|
||||
SNAP(sourceX.start, sourceX.end, SURFX.start);
|
||||
@@ -480,26 +480,35 @@ static void performSnap(Vector2D& sourcePos, Vector2D& sourceSize, PHLWINDOW DRA
|
||||
|
||||
if (*SNAPMONITORGAP) {
|
||||
const double GAPSIZE = *SNAPMONITORGAP;
|
||||
const double BORDERSIZE = OVERLAP ? 0 : DRAGGINGBORDERSIZE;
|
||||
const double BORDERDIFF = DRAGGINGBORDERSIZE - BORDERSIZE;
|
||||
const double BORDERDIFF = OVERLAP ? DRAGGINGBORDERSIZE : 0;
|
||||
const auto MON = DRAGGINGWINDOW->m_pMonitor.lock();
|
||||
|
||||
SRange monX = {MON->vecPosition.x + BORDERSIZE, MON->vecSize.x - BORDERSIZE};
|
||||
SRange monY = {MON->vecPosition.y + BORDERSIZE, MON->vecSize.y - BORDERSIZE};
|
||||
SRange monX = {MON->vecPosition.x + MON->vecReservedTopLeft.x + DRAGGINGBORDERSIZE,
|
||||
MON->vecPosition.x + MON->vecSize.x - MON->vecReservedBottomRight.x - DRAGGINGBORDERSIZE};
|
||||
SRange monY = {MON->vecPosition.y + MON->vecReservedTopLeft.y + DRAGGINGBORDERSIZE,
|
||||
MON->vecPosition.y + MON->vecSize.y - MON->vecReservedBottomRight.y - DRAGGINGBORDERSIZE};
|
||||
|
||||
if (canSnap(sourceX.start, monX.start, GAPSIZE) || canSnap(sourceX.start, (monX.start += MON->vecReservedTopLeft.x + BORDERDIFF), GAPSIZE)) {
|
||||
if (CORNER & (CORNER_TOPLEFT | CORNER_BOTTOMLEFT) &&
|
||||
((MON->vecReservedTopLeft.x > 0 && canSnap(sourceX.start, monX.start, GAPSIZE)) ||
|
||||
canSnap(sourceX.start, (monX.start -= MON->vecReservedTopLeft.x + BORDERDIFF), GAPSIZE))) {
|
||||
SNAP(sourceX.start, sourceX.end, monX.start);
|
||||
snaps |= SNAP_LEFT;
|
||||
}
|
||||
if (canSnap(sourceX.end, monX.end, GAPSIZE) || canSnap(sourceX.end, (monX.end -= MON->vecReservedBottomRight.x + BORDERDIFF), GAPSIZE)) {
|
||||
if (CORNER & (CORNER_TOPRIGHT | CORNER_BOTTOMRIGHT) &&
|
||||
((MON->vecReservedBottomRight.x > 0 && canSnap(sourceX.end, monX.end, GAPSIZE)) ||
|
||||
canSnap(sourceX.end, (monX.end += MON->vecReservedBottomRight.x + BORDERDIFF), GAPSIZE))) {
|
||||
SNAP(sourceX.end, sourceX.start, monX.end);
|
||||
snaps |= SNAP_RIGHT;
|
||||
}
|
||||
if (canSnap(sourceY.start, monY.start, GAPSIZE) || canSnap(sourceY.start, (monY.start += MON->vecReservedTopLeft.y + BORDERDIFF), GAPSIZE)) {
|
||||
if (CORNER & (CORNER_TOPLEFT | CORNER_TOPRIGHT) &&
|
||||
((MON->vecReservedTopLeft.y > 0 && canSnap(sourceY.start, monY.start, GAPSIZE)) ||
|
||||
canSnap(sourceY.start, (monY.start -= MON->vecReservedTopLeft.y + BORDERDIFF), GAPSIZE))) {
|
||||
SNAP(sourceY.start, sourceY.end, monY.start);
|
||||
snaps |= SNAP_UP;
|
||||
}
|
||||
if (canSnap(sourceY.end, monY.end, GAPSIZE) || canSnap(sourceY.end, (monY.end -= MON->vecReservedBottomRight.y + BORDERDIFF), GAPSIZE)) {
|
||||
if (CORNER & (CORNER_BOTTOMLEFT | CORNER_BOTTOMRIGHT) &&
|
||||
((MON->vecReservedBottomRight.y > 0 && canSnap(sourceY.end, monY.end, GAPSIZE)) ||
|
||||
canSnap(sourceY.end, (monY.end += MON->vecReservedBottomRight.y + BORDERDIFF), GAPSIZE))) {
|
||||
SNAP(sourceY.end, sourceY.start, monY.end);
|
||||
snaps |= SNAP_DOWN;
|
||||
}
|
||||
@@ -597,12 +606,12 @@ void IHyprLayout::onMouseMove(const Vector2D& mousePos) {
|
||||
} else if (g_pInputManager->dragMode == MBIND_RESIZE || g_pInputManager->dragMode == MBIND_RESIZE_FORCE_RATIO || g_pInputManager->dragMode == MBIND_RESIZE_BLOCK_RATIO) {
|
||||
if (DRAGGINGWINDOW->m_bIsFloating) {
|
||||
|
||||
Vector2D MINSIZE = g_pXWaylandManager->getMinSizeForWindow(DRAGGINGWINDOW).clamp(DRAGGINGWINDOW->m_sWindowData.minSize.valueOr(Vector2D(20, 20)));
|
||||
Vector2D MINSIZE = DRAGGINGWINDOW->requestedMinSize().clamp(DRAGGINGWINDOW->m_sWindowData.minSize.valueOr(Vector2D(20, 20)));
|
||||
Vector2D MAXSIZE;
|
||||
if (DRAGGINGWINDOW->m_sWindowData.maxSize.hasValue())
|
||||
MAXSIZE = g_pXWaylandManager->getMaxSizeForWindow(DRAGGINGWINDOW).clamp({}, DRAGGINGWINDOW->m_sWindowData.maxSize.value());
|
||||
MAXSIZE = DRAGGINGWINDOW->requestedMaxSize().clamp({}, DRAGGINGWINDOW->m_sWindowData.maxSize.value());
|
||||
else
|
||||
MAXSIZE = g_pXWaylandManager->getMaxSizeForWindow(DRAGGINGWINDOW).clamp({}, Vector2D(std::numeric_limits<double>::max(), std::numeric_limits<double>::max()));
|
||||
MAXSIZE = DRAGGINGWINDOW->requestedMaxSize().clamp({}, Vector2D(std::numeric_limits<double>::max(), std::numeric_limits<double>::max()));
|
||||
|
||||
Vector2D newSize = m_vBeginDragSizeXY;
|
||||
Vector2D newPos = m_vBeginDragPositionXY;
|
||||
@@ -714,7 +723,7 @@ void IHyprLayout::changeWindowFloatingMode(PHLWINDOW pWindow) {
|
||||
const auto PWORKSPACE = PNEWMON->activeSpecialWorkspace ? PNEWMON->activeSpecialWorkspace : PNEWMON->activeWorkspace;
|
||||
|
||||
if (PWORKSPACE->m_bHasFullscreenWindow)
|
||||
g_pCompositor->setWindowFullscreenInternal(g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID), FSMODE_NONE);
|
||||
g_pCompositor->setWindowFullscreenInternal(PWORKSPACE->getFullscreenWindow(), FSMODE_NONE);
|
||||
|
||||
// save real pos cuz the func applies the default 5,5 mid
|
||||
const auto PSAVEDPOS = pWindow->m_vRealPosition.goal();
|
||||
@@ -803,7 +812,7 @@ PHLWINDOW IHyprLayout::getNextWindowCandidate(PHLWINDOW pWindow) {
|
||||
|
||||
// first of all, if this is a fullscreen workspace,
|
||||
if (PWORKSPACE->m_bHasFullscreenWindow)
|
||||
return g_pCompositor->getFullscreenWindowOnWorkspace(pWindow->workspaceID());
|
||||
return PWORKSPACE->getFullscreenWindow();
|
||||
|
||||
if (pWindow->m_bIsFloating) {
|
||||
|
||||
@@ -842,10 +851,10 @@ PHLWINDOW IHyprLayout::getNextWindowCandidate(PHLWINDOW pWindow) {
|
||||
auto pWindowCandidate = g_pCompositor->vectorToWindowUnified(pWindow->middle(), RESERVED_EXTENTS | INPUT_EXTENTS | ALLOW_FLOATING);
|
||||
|
||||
if (!pWindowCandidate)
|
||||
pWindowCandidate = g_pCompositor->getTopLeftWindowOnWorkspace(pWindow->workspaceID());
|
||||
pWindowCandidate = PWORKSPACE->getTopLeftWindow();
|
||||
|
||||
if (!pWindowCandidate)
|
||||
pWindowCandidate = g_pCompositor->getFirstWindowOnWorkspace(pWindow->workspaceID());
|
||||
pWindowCandidate = PWORKSPACE->getFirstWindow();
|
||||
|
||||
if (!pWindowCandidate || pWindow == pWindowCandidate || !pWindowCandidate->m_bIsMapped || pWindowCandidate->isHidden() || pWindowCandidate->m_bX11ShouldntFocus ||
|
||||
pWindowCandidate->isX11OverrideRedirect() || pWindowCandidate->m_pMonitor != g_pCompositor->m_pLastMonitor)
|
||||
@@ -878,25 +887,26 @@ Vector2D IHyprLayout::predictSizeForNewWindowFloating(PHLWINDOW pWindow) { // ge
|
||||
Vector2D sizeOverride = {};
|
||||
if (g_pCompositor->m_pLastMonitor) {
|
||||
for (auto const& r : g_pConfigManager->getMatchingRules(pWindow, true, true)) {
|
||||
if (r.szRule.starts_with("size")) {
|
||||
try {
|
||||
const auto VALUE = r.szRule.substr(r.szRule.find(' ') + 1);
|
||||
const auto SIZEXSTR = VALUE.substr(0, VALUE.find(' '));
|
||||
const auto SIZEYSTR = VALUE.substr(VALUE.find(' ') + 1);
|
||||
if (r->ruleType != CWindowRule::RULE_SIZE)
|
||||
continue;
|
||||
|
||||
const auto MAXSIZE = g_pXWaylandManager->getMaxSizeForWindow(pWindow);
|
||||
try {
|
||||
const auto VALUE = r->szRule.substr(r->szRule.find(' ') + 1);
|
||||
const auto SIZEXSTR = VALUE.substr(0, VALUE.find(' '));
|
||||
const auto SIZEYSTR = VALUE.substr(VALUE.find(' ') + 1);
|
||||
|
||||
const float SIZEX = SIZEXSTR == "max" ? std::clamp(MAXSIZE.x, MIN_WINDOW_SIZE, g_pCompositor->m_pLastMonitor->vecSize.x) :
|
||||
stringToPercentage(SIZEXSTR, g_pCompositor->m_pLastMonitor->vecSize.x);
|
||||
const auto MAXSIZE = pWindow->requestedMaxSize();
|
||||
|
||||
const float SIZEY = SIZEYSTR == "max" ? std::clamp(MAXSIZE.y, MIN_WINDOW_SIZE, g_pCompositor->m_pLastMonitor->vecSize.y) :
|
||||
stringToPercentage(SIZEYSTR, g_pCompositor->m_pLastMonitor->vecSize.y);
|
||||
const float SIZEX = SIZEXSTR == "max" ? std::clamp(MAXSIZE.x, MIN_WINDOW_SIZE, g_pCompositor->m_pLastMonitor->vecSize.x) :
|
||||
stringToPercentage(SIZEXSTR, g_pCompositor->m_pLastMonitor->vecSize.x);
|
||||
|
||||
sizeOverride = {SIZEX, SIZEY};
|
||||
const float SIZEY = SIZEYSTR == "max" ? std::clamp(MAXSIZE.y, MIN_WINDOW_SIZE, g_pCompositor->m_pLastMonitor->vecSize.y) :
|
||||
stringToPercentage(SIZEYSTR, g_pCompositor->m_pLastMonitor->vecSize.y);
|
||||
|
||||
} catch (...) { Debug::log(LOG, "Rule size failed, rule: {} -> {}", r.szRule, r.szValue); }
|
||||
break;
|
||||
}
|
||||
sizeOverride = {SIZEX, SIZEY};
|
||||
|
||||
} catch (...) { Debug::log(LOG, "Rule size failed, rule: {} -> {}", r->szRule, r->szValue); }
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -908,10 +918,11 @@ Vector2D IHyprLayout::predictSizeForNewWindow(PHLWINDOW pWindow) {
|
||||
|
||||
if (!shouldBeFloated) {
|
||||
for (auto const& r : g_pConfigManager->getMatchingRules(pWindow, true, true)) {
|
||||
if (r.szRule.starts_with("float")) {
|
||||
shouldBeFloated = true;
|
||||
break;
|
||||
}
|
||||
if (r->ruleType != CWindowRule::RULE_FLOAT)
|
||||
continue;
|
||||
|
||||
shouldBeFloated = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -930,4 +941,4 @@ Vector2D IHyprLayout::predictSizeForNewWindow(PHLWINDOW pWindow) {
|
||||
return sizePredicted;
|
||||
}
|
||||
|
||||
IHyprLayout::~IHyprLayout() {}
|
||||
IHyprLayout::~IHyprLayout() = default;
|
||||
|
@@ -17,7 +17,7 @@ struct SLayoutMessageHeader {
|
||||
|
||||
enum eFullscreenMode : int8_t;
|
||||
|
||||
enum eRectCorner {
|
||||
enum eRectCorner : uint8_t {
|
||||
CORNER_NONE = 0,
|
||||
CORNER_TOPLEFT = (1 << 0),
|
||||
CORNER_TOPRIGHT = (1 << 1),
|
||||
@@ -25,7 +25,7 @@ enum eRectCorner {
|
||||
CORNER_BOTTOMLEFT = (1 << 3),
|
||||
};
|
||||
|
||||
enum eSnapEdge {
|
||||
enum eSnapEdge : uint8_t {
|
||||
SNAP_INVALID = 0,
|
||||
SNAP_UP = (1 << 0),
|
||||
SNAP_DOWN = (1 << 1),
|
||||
@@ -33,7 +33,7 @@ enum eSnapEdge {
|
||||
SNAP_RIGHT = (1 << 3),
|
||||
};
|
||||
|
||||
enum eDirection {
|
||||
enum eDirection : int8_t {
|
||||
DIRECTION_DEFAULT = -1,
|
||||
DIRECTION_UP = 0,
|
||||
DIRECTION_RIGHT,
|
||||
|
@@ -200,7 +200,7 @@ void CHyprMasterLayout::onWindowCreatedTiling(PHLWINDOW pWindow, eDirection dire
|
||||
PNODE->percMaster = lastSplitPercent;
|
||||
|
||||
// first, check if it isn't too big.
|
||||
if (const auto MAXSIZE = g_pXWaylandManager->getMaxSizeForWindow(pWindow); MAXSIZE.x < PMONITOR->vecSize.x * lastSplitPercent || MAXSIZE.y < PMONITOR->vecSize.y) {
|
||||
if (const auto MAXSIZE = pWindow->requestedMaxSize(); MAXSIZE.x < PMONITOR->vecSize.x * lastSplitPercent || MAXSIZE.y < PMONITOR->vecSize.y) {
|
||||
// we can't continue. make it floating.
|
||||
pWindow->m_bIsFloating = true;
|
||||
m_lMasterNodesData.remove(*PNODE);
|
||||
@@ -212,7 +212,7 @@ void CHyprMasterLayout::onWindowCreatedTiling(PHLWINDOW pWindow, eDirection dire
|
||||
PNODE->percMaster = lastSplitPercent;
|
||||
|
||||
// first, check if it isn't too big.
|
||||
if (const auto MAXSIZE = g_pXWaylandManager->getMaxSizeForWindow(pWindow);
|
||||
if (const auto MAXSIZE = pWindow->requestedMaxSize();
|
||||
MAXSIZE.x < PMONITOR->vecSize.x * (1 - lastSplitPercent) || MAXSIZE.y < PMONITOR->vecSize.y * (1.f / (WINDOWSONWORKSPACE - 1))) {
|
||||
// we can't continue. make it floating.
|
||||
pWindow->m_bIsFloating = true;
|
||||
@@ -267,7 +267,7 @@ void CHyprMasterLayout::onWindowRemovedTiling(PHLWINDOW pWindow) {
|
||||
// the screen half bare, and make it difficult to select remaining window
|
||||
if (getNodesOnWorkspace(WORKSPACEID) == 1) {
|
||||
for (auto& nd : m_lMasterNodesData) {
|
||||
if (nd.workspaceID == WORKSPACEID && nd.isMaster == false) {
|
||||
if (nd.workspaceID == WORKSPACEID && !nd.isMaster) {
|
||||
nd.isMaster = true;
|
||||
break;
|
||||
}
|
||||
@@ -298,7 +298,7 @@ void CHyprMasterLayout::calculateWorkspace(PHLWORKSPACE pWorkspace) {
|
||||
|
||||
if (pWorkspace->m_bHasFullscreenWindow) {
|
||||
// massive hack from the fullscreen func
|
||||
const auto PFULLWINDOW = g_pCompositor->getFullscreenWindowOnWorkspace(pWorkspace->m_iID);
|
||||
const auto PFULLWINDOW = pWorkspace->getFullscreenWindow();
|
||||
|
||||
if (pWorkspace->m_efFullscreenMode == FSMODE_FULLSCREEN) {
|
||||
PFULLWINDOW->m_vRealPosition = PMONITOR->vecPosition;
|
||||
@@ -328,6 +328,7 @@ void CHyprMasterLayout::calculateWorkspace(PHLWORKSPACE pWorkspace) {
|
||||
eOrientation orientation = getDynamicOrientation(pWorkspace);
|
||||
bool centerMasterWindow = false;
|
||||
static auto ALWAYSCENTER = CConfigValue<Hyprlang::INT>("master:always_center_master");
|
||||
static auto PIGNORERESERVED = CConfigValue<Hyprlang::INT>("master:center_ignores_reserved");
|
||||
static auto PSMARTRESIZING = CConfigValue<Hyprlang::INT>("master:smart_resizing");
|
||||
|
||||
const auto MASTERS = getMastersOnWorkspace(pWorkspace->m_iID);
|
||||
@@ -402,7 +403,7 @@ void CHyprMasterLayout::calculateWorkspace(PHLWORKSPACE pWorkspace) {
|
||||
nextX += WIDTH;
|
||||
}
|
||||
} else { // orientation left, right or center
|
||||
float WIDTH = WSSIZE.x;
|
||||
float WIDTH = *PIGNORERESERVED && centerMasterWindow ? PMONITOR->vecSize.x : WSSIZE.x;
|
||||
float heightLeft = WSSIZE.y;
|
||||
int mastersLeft = MASTERS;
|
||||
float nextX = 0;
|
||||
@@ -414,7 +415,7 @@ void CHyprMasterLayout::calculateWorkspace(PHLWORKSPACE pWorkspace) {
|
||||
if (orientation == ORIENTATION_RIGHT) {
|
||||
nextX = WSSIZE.x - WIDTH;
|
||||
} else if (centerMasterWindow) {
|
||||
nextX = (WSSIZE.x - WIDTH) / 2;
|
||||
nextX = ((*PIGNORERESERVED && centerMasterWindow ? PMONITOR->vecSize.x : WSSIZE.x) - WIDTH) / 2;
|
||||
}
|
||||
|
||||
for (auto& nd : m_lMasterNodesData) {
|
||||
@@ -431,7 +432,7 @@ void CHyprMasterLayout::calculateWorkspace(PHLWORKSPACE pWorkspace) {
|
||||
}
|
||||
|
||||
nd.size = Vector2D(WIDTH, HEIGHT);
|
||||
nd.position = WSPOS + Vector2D(nextX, nextY);
|
||||
nd.position = (*PIGNORERESERVED && centerMasterWindow ? PMONITOR->vecPosition : WSPOS) + Vector2D(nextX, nextY);
|
||||
applyNodeDataToWindow(&nd);
|
||||
|
||||
mastersLeft--;
|
||||
@@ -506,7 +507,7 @@ void CHyprMasterLayout::calculateWorkspace(PHLWORKSPACE pWorkspace) {
|
||||
nextY += HEIGHT;
|
||||
}
|
||||
} else { // slaves for centered master window(s)
|
||||
const float WIDTH = (WSSIZE.x - PMASTERNODE->size.x) / 2.0;
|
||||
const float WIDTH = ((*PIGNORERESERVED ? PMONITOR->vecSize.x : WSSIZE.x) - PMASTERNODE->size.x) / 2.0;
|
||||
float heightLeft = 0;
|
||||
float heightLeftL = WSSIZE.y;
|
||||
float heightLeftR = WSSIZE.y;
|
||||
@@ -543,7 +544,7 @@ void CHyprMasterLayout::calculateWorkspace(PHLWORKSPACE pWorkspace) {
|
||||
continue;
|
||||
|
||||
if (onRight) {
|
||||
nextX = WIDTH + PMASTERNODE->size.x;
|
||||
nextX = WIDTH + PMASTERNODE->size.x - (*PIGNORERESERVED ? PMONITOR->vecReservedTopLeft.x : 0);
|
||||
nextY = nextYR;
|
||||
heightLeft = heightLeftR;
|
||||
slavesLeft = slavesLeftR;
|
||||
@@ -568,7 +569,7 @@ void CHyprMasterLayout::calculateWorkspace(PHLWORKSPACE pWorkspace) {
|
||||
}
|
||||
}
|
||||
|
||||
nd.size = Vector2D(WIDTH, HEIGHT);
|
||||
nd.size = Vector2D(*PIGNORERESERVED ? (WIDTH - (onRight ? PMONITOR->vecReservedBottomRight.x : PMONITOR->vecReservedTopLeft.x)) : WIDTH, HEIGHT);
|
||||
nd.position = WSPOS + Vector2D(nextX, nextY);
|
||||
applyNodeDataToWindow(&nd);
|
||||
|
||||
|
@@ -5,7 +5,7 @@
|
||||
#include "../config/ConfigManager.hpp"
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <deque>
|
||||
#include <vector>
|
||||
#include <any>
|
||||
|
||||
enum eFullscreenMode : int8_t;
|
||||
|
@@ -16,8 +16,6 @@
|
||||
#define ISDEBUG false
|
||||
#endif
|
||||
|
||||
#include "version.h"
|
||||
|
||||
#define SPECIAL_WORKSPACE_START (-99)
|
||||
|
||||
#define PI 3.14159265358979
|
||||
|
26
src/main.cpp
26
src/main.cpp
@@ -54,11 +54,11 @@ int main(int argc, char** argv) {
|
||||
std::vector<std::string> args{argv + 1, argv + argc};
|
||||
|
||||
for (auto it = args.begin(); it != args.end(); it++) {
|
||||
if (it->compare("--i-am-really-stupid") == 0 && !ignoreSudo) {
|
||||
if (*it == "--i-am-really-stupid" && !ignoreSudo) {
|
||||
std::println("[ WARNING ] Running Hyprland with superuser privileges might damage your system");
|
||||
|
||||
ignoreSudo = true;
|
||||
} else if (it->compare("--socket") == 0) {
|
||||
} else if (*it == "--socket") {
|
||||
if (std::next(it) == args.end()) {
|
||||
help();
|
||||
|
||||
@@ -67,7 +67,7 @@ int main(int argc, char** argv) {
|
||||
|
||||
socketName = *std::next(it);
|
||||
it++;
|
||||
} else if (it->compare("--wayland-fd") == 0) {
|
||||
} else if (*it == "--wayland-fd") {
|
||||
if (std::next(it) == args.end()) {
|
||||
help();
|
||||
|
||||
@@ -75,7 +75,7 @@ int main(int argc, char** argv) {
|
||||
}
|
||||
|
||||
try {
|
||||
socketFd = std::stoi(std::next(it)->c_str());
|
||||
socketFd = std::stoi(*std::next(it));
|
||||
|
||||
// check if socketFd is a valid file descriptor
|
||||
if (fcntl(socketFd, F_GETFD) == -1)
|
||||
@@ -88,13 +88,13 @@ int main(int argc, char** argv) {
|
||||
}
|
||||
|
||||
it++;
|
||||
} else if (it->compare("-c") == 0 || it->compare("--config") == 0) {
|
||||
} else if (*it == "-c" || *it == "--config") {
|
||||
if (std::next(it) == args.end()) {
|
||||
help();
|
||||
|
||||
return 1;
|
||||
}
|
||||
configPath = std::next(it)->c_str();
|
||||
configPath = *std::next(it);
|
||||
|
||||
try {
|
||||
configPath = std::filesystem::canonical(configPath);
|
||||
@@ -114,31 +114,31 @@ int main(int argc, char** argv) {
|
||||
it++;
|
||||
|
||||
continue;
|
||||
} else if (it->compare("-h") == 0 || it->compare("--help") == 0) {
|
||||
} else if (*it == "-h" || *it == "--help") {
|
||||
help();
|
||||
|
||||
return 0;
|
||||
} else if (it->compare("-v") == 0 || it->compare("--version") == 0) {
|
||||
} else if (*it == "-v" || *it == "--version") {
|
||||
std::println("{}", versionRequest(eHyprCtlOutputFormat::FORMAT_NORMAL, ""));
|
||||
return 0;
|
||||
} else if (it->compare("--systeminfo") == 0) {
|
||||
} else if (*it == "--systeminfo") {
|
||||
std::println("{}", systemInfoRequest(eHyprCtlOutputFormat::FORMAT_NORMAL, ""));
|
||||
return 0;
|
||||
} else {
|
||||
std::println(stderr, "[ ERROR ] Unknown option '{}' !", it->c_str());
|
||||
std::println(stderr, "[ ERROR ] Unknown option '{}' !", *it);
|
||||
help();
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ignoreSudo && Init::isSudo()) {
|
||||
if (!ignoreSudo && NInit::isSudo()) {
|
||||
std::println(stderr,
|
||||
"[ ERROR ] Hyprland was launched with superuser privileges, but the privileges check is not omitted.\n"
|
||||
" Hint: Use the --i-am-really-stupid flag to omit that check.");
|
||||
|
||||
return 1;
|
||||
} else if (ignoreSudo && Init::isSudo()) {
|
||||
} else if (ignoreSudo && NInit::isSudo()) {
|
||||
std::println("Superuser privileges check is omitted. I hope you know what you're doing.");
|
||||
}
|
||||
|
||||
@@ -165,7 +165,7 @@ int main(int argc, char** argv) {
|
||||
g_pCompositor->initServer(socketName, socketFd);
|
||||
|
||||
if (!envEnabled("HYPRLAND_NO_RT"))
|
||||
Init::gainRealTime();
|
||||
NInit::gainRealTime();
|
||||
|
||||
Debug::log(LOG, "Hyprland init finished.");
|
||||
|
||||
|
@@ -8,6 +8,8 @@
|
||||
#include "eventLoop/EventLoopManager.hpp"
|
||||
#include "../helpers/varlist/VarList.hpp"
|
||||
|
||||
#include <hyprgraphics/color/Color.hpp>
|
||||
|
||||
int wlTick(SP<CEventLoopTimer> self, void* data) {
|
||||
if (g_pAnimationManager)
|
||||
g_pAnimationManager->onTicked();
|
||||
@@ -149,14 +151,14 @@ void CAnimationManager::tick() {
|
||||
animationsDisabled = animationsDisabled || PLAYER->noAnimations;
|
||||
}
|
||||
|
||||
const bool VISIBLE = PWINDOW && PWINDOW->m_pWorkspace ? g_pCompositor->isWorkspaceVisible(PWINDOW->m_pWorkspace) : true;
|
||||
const bool VISIBLE = PWINDOW && PWINDOW->m_pWorkspace ? PWINDOW->m_pWorkspace->isVisible() : true;
|
||||
|
||||
// beziers are with a switch unforto
|
||||
// TODO: maybe do something cleaner
|
||||
|
||||
auto updateVariable = [&]<Animable T>(CAnimatedVariable<T>& av) {
|
||||
static const auto updateVariable = [this]<Animable T>(CAnimatedVariable<T>& av, const float SPENT, const CBezierCurve& DEFAULTBEZIER, const bool DISABLED) {
|
||||
// for disabled anims just warp
|
||||
if (av.m_pConfig->pValues->internalEnabled == 0 || animationsDisabled) {
|
||||
if (av.m_pConfig->pValues->internalEnabled == 0 || DISABLED) {
|
||||
av.warp(false);
|
||||
return;
|
||||
}
|
||||
@@ -166,29 +168,66 @@ void CAnimationManager::tick() {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto DELTA = av.m_Goal - av.m_Begun;
|
||||
const auto BEZIER = m_mBezierCurves.find(av.m_pConfig->pValues->internalBezier);
|
||||
const auto POINTY = BEZIER != m_mBezierCurves.end() ? BEZIER->second.getYForPoint(SPENT) : DEFAULTBEZIER.getYForPoint(SPENT);
|
||||
|
||||
const auto DELTA = av.m_Goal - av.m_Begun;
|
||||
|
||||
if (BEZIER != m_mBezierCurves.end())
|
||||
av.m_Value = av.m_Begun + DELTA * BEZIER->second.getYForPoint(SPENT);
|
||||
av.m_Value = av.m_Begun + DELTA * POINTY;
|
||||
else
|
||||
av.m_Value = av.m_Begun + DELTA * DEFAULTBEZIER->second.getYForPoint(SPENT);
|
||||
av.m_Value = av.m_Begun + DELTA * POINTY;
|
||||
};
|
||||
|
||||
static const auto updateColorVariable = [this](CAnimatedVariable<CHyprColor>& av, const float SPENT, const CBezierCurve& DEFAULTBEZIER, const bool DISABLED) {
|
||||
// for disabled anims just warp
|
||||
if (av.m_pConfig->pValues->internalEnabled == 0 || DISABLED) {
|
||||
av.warp(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (SPENT >= 1.f || av.m_Begun == av.m_Goal) {
|
||||
av.warp(false);
|
||||
return;
|
||||
}
|
||||
|
||||
const auto BEZIER = m_mBezierCurves.find(av.m_pConfig->pValues->internalBezier);
|
||||
const auto POINTY = BEZIER != m_mBezierCurves.end() ? BEZIER->second.getYForPoint(SPENT) : DEFAULTBEZIER.getYForPoint(SPENT);
|
||||
|
||||
// convert both to OkLab, then lerp that, and convert back.
|
||||
// This is not as fast as just lerping rgb, but it's WAY more precise...
|
||||
// Use the CHyprColor cache for OkLab
|
||||
|
||||
const auto& L1 = av.m_Begun.asOkLab();
|
||||
const auto& L2 = av.m_Goal.asOkLab();
|
||||
|
||||
static const auto lerp = [](const float one, const float two, const float progress) -> float { return one + (two - one) * progress; };
|
||||
|
||||
const Hyprgraphics::CColor lerped = Hyprgraphics::CColor::SOkLab{
|
||||
.l = lerp(L1.l, L2.l, POINTY),
|
||||
.a = lerp(L1.a, L2.a, POINTY),
|
||||
.b = lerp(L1.b, L2.b, POINTY),
|
||||
};
|
||||
|
||||
av.m_Value = {lerped, lerp(av.m_Begun.a, av.m_Goal.a, POINTY)};
|
||||
|
||||
return;
|
||||
};
|
||||
|
||||
switch (av->m_Type) {
|
||||
case AVARTYPE_FLOAT: {
|
||||
auto typedAv = static_cast<CAnimatedVariable<float>*>(av);
|
||||
updateVariable(*typedAv);
|
||||
auto typedAv = dynamic_cast<CAnimatedVariable<float>*>(av);
|
||||
updateVariable(*typedAv, SPENT, DEFAULTBEZIER->second, animationsDisabled);
|
||||
break;
|
||||
}
|
||||
case AVARTYPE_VECTOR: {
|
||||
auto typedAv = static_cast<CAnimatedVariable<Vector2D>*>(av);
|
||||
updateVariable(*typedAv);
|
||||
auto typedAv = dynamic_cast<CAnimatedVariable<Vector2D>*>(av);
|
||||
updateVariable(*typedAv, SPENT, DEFAULTBEZIER->second, animationsDisabled);
|
||||
break;
|
||||
}
|
||||
case AVARTYPE_COLOR: {
|
||||
auto typedAv = static_cast<CAnimatedVariable<CColor>*>(av);
|
||||
updateVariable(*typedAv);
|
||||
auto typedAv = dynamic_cast<CAnimatedVariable<CHyprColor>*>(av);
|
||||
updateColorVariable(*typedAv, SPENT, DEFAULTBEZIER->second, animationsDisabled);
|
||||
break;
|
||||
}
|
||||
default: UNREACHABLE();
|
||||
@@ -262,7 +301,7 @@ void CAnimationManager::tick() {
|
||||
g_pCompositor->scheduleFrameForMonitor(PMONITOR, Aquamarine::IOutput::AQ_SCHEDULE_ANIMATION);
|
||||
}
|
||||
|
||||
// do it here, because if this alters the animation vars deque we would be in trouble above.
|
||||
// do it here, because if this alters the animation vars vec we would be in trouble above.
|
||||
for (auto const& ave : animationEndedVars) {
|
||||
ave->onAnimationEnd();
|
||||
}
|
||||
@@ -272,7 +311,7 @@ bool CAnimationManager::deltaSmallToFlip(const Vector2D& a, const Vector2D& b) {
|
||||
return std::abs(a.x - b.x) < 0.5f && std::abs(a.y - b.y) < 0.5f;
|
||||
}
|
||||
|
||||
bool CAnimationManager::deltaSmallToFlip(const CColor& a, const CColor& b) {
|
||||
bool CAnimationManager::deltaSmallToFlip(const CHyprColor& a, const CHyprColor& b) {
|
||||
return std::abs(a.r - b.r) < 0.5f && std::abs(a.g - b.g) < 0.5f && std::abs(a.b - b.b) < 0.5f && std::abs(a.a - b.a) < 0.5f;
|
||||
}
|
||||
|
||||
@@ -288,7 +327,7 @@ bool CAnimationManager::deltazero(const float& a, const float& b) {
|
||||
return a == b;
|
||||
}
|
||||
|
||||
bool CAnimationManager::deltazero(const CColor& a, const CColor& b) {
|
||||
bool CAnimationManager::deltazero(const CHyprColor& a, const CHyprColor& b) {
|
||||
return a.r == b.r && a.g == b.g && a.b == b.b && a.a == b.a;
|
||||
}
|
||||
|
||||
@@ -456,7 +495,7 @@ std::string CAnimationManager::styleValidInConfigVar(const std::string& config,
|
||||
else if (style.starts_with("popin")) {
|
||||
// try parsing
|
||||
float minPerc = 0.f;
|
||||
if (style.find("%") != std::string::npos) {
|
||||
if (style.find('%') != std::string::npos) {
|
||||
try {
|
||||
auto percstr = style.substr(style.find_last_of(' '));
|
||||
minPerc = std::stoi(percstr.substr(0, percstr.length() - 1));
|
||||
@@ -477,7 +516,7 @@ std::string CAnimationManager::styleValidInConfigVar(const std::string& config,
|
||||
else if (style.starts_with("slidefade")) {
|
||||
// try parsing
|
||||
float movePerc = 0.f;
|
||||
if (style.find("%") != std::string::npos) {
|
||||
if (style.find('%') != std::string::npos) {
|
||||
try {
|
||||
auto percstr = style.substr(style.find_last_of(' ') + 1);
|
||||
movePerc = std::stoi(percstr.substr(0, percstr.length() - 1));
|
||||
@@ -502,7 +541,7 @@ std::string CAnimationManager::styleValidInConfigVar(const std::string& config,
|
||||
else if (style.starts_with("popin")) {
|
||||
// try parsing
|
||||
float minPerc = 0.f;
|
||||
if (style.find("%") != std::string::npos) {
|
||||
if (style.find('%') != std::string::npos) {
|
||||
try {
|
||||
auto percstr = style.substr(style.find_last_of(' '));
|
||||
minPerc = std::stoi(percstr.substr(0, percstr.length() - 1));
|
||||
|
@@ -39,10 +39,10 @@ class CAnimationManager {
|
||||
|
||||
private:
|
||||
bool deltaSmallToFlip(const Vector2D& a, const Vector2D& b);
|
||||
bool deltaSmallToFlip(const CColor& a, const CColor& b);
|
||||
bool deltaSmallToFlip(const CHyprColor& a, const CHyprColor& b);
|
||||
bool deltaSmallToFlip(const float& a, const float& b);
|
||||
bool deltazero(const Vector2D& a, const Vector2D& b);
|
||||
bool deltazero(const CColor& a, const CColor& b);
|
||||
bool deltazero(const CHyprColor& a, const CHyprColor& b);
|
||||
bool deltazero(const float& a, const float& b);
|
||||
|
||||
std::unordered_map<std::string, CBezierCurve> m_mBezierCurves;
|
||||
|
@@ -17,16 +17,12 @@ static void hcLogger(enum eHyprcursorLogLevel level, char* message) {
|
||||
Debug::log(NONE, "[hc] {}", message);
|
||||
}
|
||||
|
||||
CCursorBuffer::CCursorBuffer(cairo_surface_t* surf, const Vector2D& size_, const Vector2D& hot_) : hotspot(hot_) {
|
||||
surface = surf;
|
||||
size = size_;
|
||||
stride = cairo_image_surface_get_stride(surf);
|
||||
CCursorBuffer::CCursorBuffer(cairo_surface_t* surf, const Vector2D& size_, const Vector2D& hot_) : hotspot(hot_), surface(surf), stride(cairo_image_surface_get_stride(surf)) {
|
||||
size = size_;
|
||||
}
|
||||
|
||||
CCursorBuffer::CCursorBuffer(uint8_t* pixelData_, const Vector2D& size_, const Vector2D& hot_) : hotspot(hot_) {
|
||||
pixelData = pixelData_;
|
||||
size = size_;
|
||||
stride = 4 * size_.x;
|
||||
CCursorBuffer::CCursorBuffer(uint8_t* pixelData_, const Vector2D& size_, const Vector2D& hot_) : hotspot(hot_), pixelData(pixelData_), stride(4 * size_.x) {
|
||||
size = size_;
|
||||
}
|
||||
|
||||
Aquamarine::eBufferCapability CCursorBuffer::caps() {
|
||||
|
@@ -10,8 +10,7 @@
|
||||
#include <unistd.h>
|
||||
#include <cstring>
|
||||
|
||||
CEventManager::CEventManager() {
|
||||
m_iSocketFD = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0);
|
||||
CEventManager::CEventManager() : m_iSocketFD(socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0)) {
|
||||
if (m_iSocketFD < 0) {
|
||||
Debug::log(ERR, "Couldn't start the Hyprland Socket 2. (1) IPC will not work.");
|
||||
return;
|
||||
@@ -117,7 +116,7 @@ int CEventManager::onClientEvent(int fd, uint32_t mask) {
|
||||
if (write(CLIENTIT->fd, event->c_str(), event->length()) < 0)
|
||||
break;
|
||||
|
||||
CLIENTIT->events.pop_front();
|
||||
CLIENTIT->events.erase(CLIENTIT->events.begin());
|
||||
}
|
||||
|
||||
// stop polling when we sent all events
|
||||
|
@@ -1,5 +1,5 @@
|
||||
#pragma once
|
||||
#include <deque>
|
||||
#include <vector>
|
||||
#include <vector>
|
||||
|
||||
#include "../defines.hpp"
|
||||
@@ -27,9 +27,9 @@ class CEventManager {
|
||||
int onClientEvent(int fd, uint32_t mask);
|
||||
|
||||
struct SClient {
|
||||
int fd = -1;
|
||||
std::deque<SP<std::string>> events;
|
||||
wl_event_source* eventSource = nullptr;
|
||||
int fd = -1;
|
||||
std::vector<SP<std::string>> events;
|
||||
wl_event_source* eventSource = nullptr;
|
||||
};
|
||||
|
||||
std::vector<SClient>::iterator findClientByFD(int fd);
|
||||
|
@@ -5,7 +5,6 @@
|
||||
#include "../protocols/ShortcutsInhibit.hpp"
|
||||
#include "../protocols/GlobalShortcuts.hpp"
|
||||
#include "../render/decorations/CHyprGroupBarDecoration.hpp"
|
||||
#include "../devices/IKeyboard.hpp"
|
||||
#include "KeybindManager.hpp"
|
||||
#include "PointerManager.hpp"
|
||||
#include "Compositor.hpp"
|
||||
@@ -130,9 +129,44 @@ CKeybindManager::CKeybindManager() {
|
||||
|
||||
m_tScrollTimer.reset();
|
||||
|
||||
m_pLongPressTimer = makeShared<CEventLoopTimer>(
|
||||
std::nullopt,
|
||||
[this](SP<CEventLoopTimer> self, void* data) {
|
||||
if (!m_pLastLongPressKeybind || g_pSeatManager->keyboard.expired())
|
||||
return;
|
||||
|
||||
const auto DISPATCHER = g_pKeybindManager->m_mDispatchers.find(m_pLastLongPressKeybind->handler);
|
||||
|
||||
Debug::log(LOG, "Long press timeout passed, calling dispatcher.");
|
||||
DISPATCHER->second(m_pLastLongPressKeybind->arg);
|
||||
},
|
||||
nullptr);
|
||||
|
||||
m_pRepeatKeyTimer = makeShared<CEventLoopTimer>(
|
||||
std::nullopt,
|
||||
[this](SP<CEventLoopTimer> self, void* data) {
|
||||
if (m_vActiveKeybinds.size() == 0 || g_pSeatManager->keyboard.expired())
|
||||
return;
|
||||
|
||||
for (const auto& k : m_vActiveKeybinds) {
|
||||
const auto DISPATCHER = g_pKeybindManager->m_mDispatchers.find(k->handler);
|
||||
|
||||
Debug::log(LOG, "Keybind repeat triggered, calling dispatcher.");
|
||||
DISPATCHER->second(k->arg);
|
||||
}
|
||||
|
||||
const auto PACTIVEKEEB = g_pSeatManager->keyboard.lock();
|
||||
self->updateTimeout(std::chrono::milliseconds(1000 / PACTIVEKEEB->repeatRate));
|
||||
},
|
||||
nullptr);
|
||||
|
||||
g_pEventLoopManager->addTimer(m_pLongPressTimer);
|
||||
g_pEventLoopManager->addTimer(m_pRepeatKeyTimer);
|
||||
|
||||
static auto P = g_pHookSystem->hookDynamic("configReloaded", [this](void* hk, SCallbackInfo& info, std::any param) {
|
||||
// clear cuz realloc'd
|
||||
m_pActiveKeybind = nullptr;
|
||||
m_vActiveKeybinds.clear();
|
||||
m_pLastLongPressKeybind.reset();
|
||||
m_vPressedSpecialBinds.clear();
|
||||
});
|
||||
}
|
||||
@@ -140,25 +174,28 @@ CKeybindManager::CKeybindManager() {
|
||||
CKeybindManager::~CKeybindManager() {
|
||||
if (m_pXKBTranslationState)
|
||||
xkb_state_unref(m_pXKBTranslationState);
|
||||
if (m_pLongPressTimer && g_pEventLoopManager) {
|
||||
g_pEventLoopManager->removeTimer(m_pLongPressTimer);
|
||||
m_pLongPressTimer.reset();
|
||||
}
|
||||
if (m_pRepeatKeyTimer && g_pEventLoopManager) {
|
||||
g_pEventLoopManager->removeTimer(m_pRepeatKeyTimer);
|
||||
m_pRepeatKeyTimer.reset();
|
||||
}
|
||||
}
|
||||
|
||||
void CKeybindManager::addKeybind(SKeybind kb) {
|
||||
m_lKeybinds.push_back(kb);
|
||||
m_vKeybinds.emplace_back(makeShared<SKeybind>(kb));
|
||||
|
||||
m_pActiveKeybind = nullptr;
|
||||
m_vActiveKeybinds.clear();
|
||||
m_pLastLongPressKeybind.reset();
|
||||
}
|
||||
|
||||
void CKeybindManager::removeKeybind(uint32_t mod, const SParsedKey& key) {
|
||||
for (auto it = m_lKeybinds.begin(); it != m_lKeybinds.end(); ++it) {
|
||||
if (it->modmask == mod && it->key == key.key && it->keycode == key.keycode && it->catchAll == key.catchAll) {
|
||||
it = m_lKeybinds.erase(it);
|
||||
std::erase_if(m_vKeybinds, [&mod, &key](const auto& el) { return el->modmask == mod && el->key == key.key && el->keycode == key.keycode && el->catchAll == key.catchAll; });
|
||||
|
||||
if (it == m_lKeybinds.end())
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
m_pActiveKeybind = nullptr;
|
||||
m_vActiveKeybinds.clear();
|
||||
m_pLastLongPressKeybind.reset();
|
||||
}
|
||||
|
||||
uint32_t CKeybindManager::stringToModMask(std::string mods) {
|
||||
@@ -226,7 +263,7 @@ void CKeybindManager::updateXKBTranslationState() {
|
||||
|
||||
xkb_rule_names rules = {.rules = RULES.c_str(), .model = MODEL.c_str(), .layout = LAYOUT.c_str(), .variant = VARIANT.c_str(), .options = OPTIONS.c_str()};
|
||||
const auto PCONTEXT = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
|
||||
FILE* const KEYMAPFILE = FILEPATH == "" ? NULL : fopen(absolutePath(FILEPATH, g_pConfigManager->configCurrentPath).c_str(), "r");
|
||||
FILE* const KEYMAPFILE = FILEPATH == "" ? nullptr : fopen(absolutePath(FILEPATH, g_pConfigManager->configCurrentPath).c_str(), "r");
|
||||
|
||||
auto PKEYMAP = KEYMAPFILE ? xkb_keymap_new_from_file(PCONTEXT, KEYMAPFILE, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS) :
|
||||
xkb_keymap_new_from_names(PCONTEXT, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS);
|
||||
@@ -236,7 +273,7 @@ void CKeybindManager::updateXKBTranslationState() {
|
||||
if (!PKEYMAP) {
|
||||
g_pHyprError->queueCreate("[Runtime Error] Invalid keyboard layout passed. ( rules: " + RULES + ", model: " + MODEL + ", variant: " + VARIANT + ", options: " + OPTIONS +
|
||||
", layout: " + LAYOUT + " )",
|
||||
CColor(1.0, 50.0 / 255.0, 50.0 / 255.0, 1.0));
|
||||
CHyprColor(1.0, 50.0 / 255.0, 50.0 / 255.0, 1.0));
|
||||
|
||||
Debug::log(ERR, "[XKBTranslationState] Keyboard layout {} with variant {} (rules: {}, model: {}, options: {}) couldn't have been loaded.", rules.layout, rules.variant,
|
||||
rules.rules, rules.model, rules.options);
|
||||
@@ -338,6 +375,10 @@ void CKeybindManager::switchToWindow(PHLWINDOW PWINDOWTOCHANGETO) {
|
||||
|
||||
if (!PWINDOWTOCHANGETO->m_bPinned)
|
||||
g_pCompositor->setWindowFullscreenInternal(PWINDOWTOCHANGETO, MODE);
|
||||
|
||||
// warp the position + size animation, otherwise it looks weird.
|
||||
PWINDOWTOCHANGETO->m_vRealPosition.warp();
|
||||
PWINDOWTOCHANGETO->m_vRealSize.warp();
|
||||
} else {
|
||||
updateRelativeCursorCoords();
|
||||
g_pCompositor->focusWindow(PWINDOWTOCHANGETO);
|
||||
@@ -366,7 +407,7 @@ bool CKeybindManager::onKeyEvent(std::any event, SP<IKeyboard> pKeyboard) {
|
||||
}
|
||||
|
||||
if (!m_pXKBTranslationState) {
|
||||
Debug::log(ERR, "BUG THIS: m_pXKBTranslationState NULL!");
|
||||
Debug::log(ERR, "BUG THIS: m_pXKBTranslationState nullptr!");
|
||||
updateXKBTranslationState();
|
||||
|
||||
if (!m_pXKBTranslationState)
|
||||
@@ -380,8 +421,10 @@ bool CKeybindManager::onKeyEvent(std::any event, SP<IKeyboard> pKeyboard) {
|
||||
const xkb_keysym_t keysym = xkb_state_key_get_one_sym(pKeyboard->resolveBindsBySym ? pKeyboard->xkbSymState : m_pXKBTranslationState, KEYCODE);
|
||||
const xkb_keysym_t internalKeysym = xkb_state_key_get_one_sym(pKeyboard->xkbState, KEYCODE);
|
||||
|
||||
// handleInternalKeybinds returns true when the key should be suppressed,
|
||||
// while this function returns true when the key event should be sent
|
||||
if (handleInternalKeybinds(internalKeysym))
|
||||
return true;
|
||||
return false;
|
||||
|
||||
const auto MODS = g_pInputManager->accumulateModsFromAllKBs();
|
||||
|
||||
@@ -399,11 +442,9 @@ bool CKeybindManager::onKeyEvent(std::any event, SP<IKeyboard> pKeyboard) {
|
||||
.submapAtPress = m_szCurrentSelectedSubmap,
|
||||
};
|
||||
|
||||
if (m_pActiveKeybindEventSource) {
|
||||
wl_event_source_remove(m_pActiveKeybindEventSource);
|
||||
m_pActiveKeybindEventSource = nullptr;
|
||||
m_pActiveKeybind = nullptr;
|
||||
}
|
||||
m_vActiveKeybinds.clear();
|
||||
|
||||
m_pLastLongPressKeybind.reset();
|
||||
|
||||
bool suppressEvent = false;
|
||||
if (e.state == WL_KEYBOARD_KEY_STATE_PRESSED) {
|
||||
@@ -453,11 +494,7 @@ bool CKeybindManager::onAxisEvent(const IPointer::SAxisEvent& e) {
|
||||
|
||||
m_tScrollTimer.reset();
|
||||
|
||||
if (m_pActiveKeybindEventSource) {
|
||||
wl_event_source_remove(m_pActiveKeybindEventSource);
|
||||
m_pActiveKeybindEventSource = nullptr;
|
||||
m_pActiveKeybind = nullptr;
|
||||
}
|
||||
m_vActiveKeybinds.clear();
|
||||
|
||||
bool found = false;
|
||||
if (e.source == WL_POINTER_AXIS_SOURCE_WHEEL && e.axis == WL_POINTER_AXIS_VERTICAL_SCROLL) {
|
||||
@@ -496,11 +533,7 @@ bool CKeybindManager::onMouseEvent(const IPointer::SButtonEvent& e) {
|
||||
.modmaskAtPressTime = MODS,
|
||||
};
|
||||
|
||||
if (m_pActiveKeybindEventSource) {
|
||||
wl_event_source_remove(m_pActiveKeybindEventSource);
|
||||
m_pActiveKeybindEventSource = nullptr;
|
||||
m_pActiveKeybind = nullptr;
|
||||
}
|
||||
m_vActiveKeybinds.clear();
|
||||
|
||||
if (e.state == WL_POINTER_BUTTON_STATE_PRESSED) {
|
||||
m_dPressedKeys.push_back(KEY);
|
||||
@@ -551,22 +584,6 @@ void CKeybindManager::onSwitchOffEvent(const std::string& switchName) {
|
||||
handleKeybinds(0, SPressedKeyWithMods{.keyName = "switch:off:" + switchName}, true);
|
||||
}
|
||||
|
||||
int repeatKeyHandler(void* data) {
|
||||
SKeybind** ppActiveKeybind = (SKeybind**)data;
|
||||
|
||||
if (!*ppActiveKeybind || g_pSeatManager->keyboard.expired())
|
||||
return 0;
|
||||
|
||||
const auto DISPATCHER = g_pKeybindManager->m_mDispatchers.find((*ppActiveKeybind)->handler);
|
||||
|
||||
Debug::log(LOG, "Keybind repeat triggered, calling dispatcher.");
|
||||
DISPATCHER->second((*ppActiveKeybind)->arg);
|
||||
|
||||
wl_event_source_timer_update(g_pKeybindManager->m_pActiveKeybindEventSource, 1000 / g_pSeatManager->keyboard->repeatRate);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
eMultiKeyCase CKeybindManager::mkKeysymSetMatches(const std::set<xkb_keysym_t> keybindKeysyms, const std::set<xkb_keysym_t> pressedKeysyms) {
|
||||
// Returns whether two sets of keysyms are equal, partially equal, or not
|
||||
// matching. (Partially matching means that pressed is a subset of bound)
|
||||
@@ -588,11 +605,11 @@ eMultiKeyCase CKeybindManager::mkKeysymSetMatches(const std::set<xkb_keysym_t> k
|
||||
return MK_NO_MATCH;
|
||||
}
|
||||
|
||||
eMultiKeyCase CKeybindManager::mkBindMatches(const SKeybind keybind) {
|
||||
if (mkKeysymSetMatches(keybind.sMkMods, m_sMkMods) != MK_FULL_MATCH)
|
||||
eMultiKeyCase CKeybindManager::mkBindMatches(const SP<SKeybind> keybind) {
|
||||
if (mkKeysymSetMatches(keybind->sMkMods, m_sMkMods) != MK_FULL_MATCH)
|
||||
return MK_NO_MATCH;
|
||||
|
||||
return mkKeysymSetMatches(keybind.sMkKeys, m_sMkKeys);
|
||||
return mkKeysymSetMatches(keybind->sMkKeys, m_sMkKeys);
|
||||
}
|
||||
|
||||
std::string CKeybindManager::getCurrentSubmap() {
|
||||
@@ -616,35 +633,35 @@ SDispatchResult CKeybindManager::handleKeybinds(const uint32_t modmask, const SP
|
||||
m_sMkKeys.erase(key.keysym);
|
||||
}
|
||||
|
||||
for (auto& k : m_lKeybinds) {
|
||||
const bool SPECIALDISPATCHER = k.handler == "global" || k.handler == "pass" || k.handler == "sendshortcut" || k.handler == "mouse";
|
||||
for (auto& k : m_vKeybinds) {
|
||||
const bool SPECIALDISPATCHER = k->handler == "global" || k->handler == "pass" || k->handler == "sendshortcut" || k->handler == "mouse";
|
||||
const bool SPECIALTRIGGERED =
|
||||
std::find_if(m_vPressedSpecialBinds.begin(), m_vPressedSpecialBinds.end(), [&](const auto& other) { return other == &k; }) != m_vPressedSpecialBinds.end();
|
||||
std::find_if(m_vPressedSpecialBinds.begin(), m_vPressedSpecialBinds.end(), [&](const auto& other) { return other == k; }) != m_vPressedSpecialBinds.end();
|
||||
const bool IGNORECONDITIONS =
|
||||
SPECIALDISPATCHER && !pressed && SPECIALTRIGGERED; // ignore mods. Pass, global dispatchers should be released immediately once the key is released.
|
||||
|
||||
if (!k.dontInhibit && !*PDISABLEINHIBIT && PROTO::shortcutsInhibit->isInhibited())
|
||||
if (!k->dontInhibit && !*PDISABLEINHIBIT && PROTO::shortcutsInhibit->isInhibited())
|
||||
continue;
|
||||
|
||||
if (!k.locked && g_pSessionLockManager->isSessionLocked())
|
||||
if (!k->locked && g_pSessionLockManager->isSessionLocked())
|
||||
continue;
|
||||
|
||||
if (!IGNORECONDITIONS && ((modmask != k.modmask && !k.ignoreMods) || k.submap != m_szCurrentSelectedSubmap || k.shadowed))
|
||||
if (!IGNORECONDITIONS && ((modmask != k->modmask && !k->ignoreMods) || k->submap != m_szCurrentSelectedSubmap || k->shadowed))
|
||||
continue;
|
||||
|
||||
if (k.multiKey) {
|
||||
if (k->multiKey) {
|
||||
switch (mkBindMatches(k)) {
|
||||
case MK_NO_MATCH: continue;
|
||||
case MK_PARTIAL_MATCH: found = true; continue;
|
||||
case MK_FULL_MATCH: found = true;
|
||||
}
|
||||
} else if (!key.keyName.empty()) {
|
||||
if (key.keyName != k.key)
|
||||
if (key.keyName != k->key)
|
||||
continue;
|
||||
} else if (k.keycode != 0) {
|
||||
if (key.keycode != k.keycode)
|
||||
} else if (k->keycode != 0) {
|
||||
if (key.keycode != k->keycode)
|
||||
continue;
|
||||
} else if (k.catchAll) {
|
||||
} else if (k->catchAll) {
|
||||
if (found || key.submapAtPress != m_szCurrentSelectedSubmap)
|
||||
continue;
|
||||
} else {
|
||||
@@ -655,8 +672,8 @@ SDispatchResult CKeybindManager::handleKeybinds(const uint32_t modmask, const SP
|
||||
|
||||
// oMg such performance hit!!11!
|
||||
// this little maneouver is gonna cost us 4µs
|
||||
const auto KBKEY = xkb_keysym_from_name(k.key.c_str(), XKB_KEYSYM_NO_FLAGS);
|
||||
const auto KBKEYLOWER = xkb_keysym_from_name(k.key.c_str(), XKB_KEYSYM_CASE_INSENSITIVE);
|
||||
const auto KBKEY = xkb_keysym_from_name(k->key.c_str(), XKB_KEYSYM_NO_FLAGS);
|
||||
const auto KBKEYLOWER = xkb_keysym_from_name(k->key.c_str(), XKB_KEYSYM_CASE_INSENSITIVE);
|
||||
|
||||
if (KBKEY == XKB_KEY_NoSymbol && KBKEYLOWER == XKB_KEY_NoSymbol) {
|
||||
// Keysym failed to resolve from the key name of the currently iterated bind.
|
||||
@@ -673,8 +690,8 @@ SDispatchResult CKeybindManager::handleKeybinds(const uint32_t modmask, const SP
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pressed && k.release && !SPECIALDISPATCHER) {
|
||||
if (k.nonConsuming)
|
||||
if (pressed && k->release && !SPECIALDISPATCHER) {
|
||||
if (k->nonConsuming)
|
||||
continue;
|
||||
|
||||
found = true; // suppress the event
|
||||
@@ -683,7 +700,7 @@ SDispatchResult CKeybindManager::handleKeybinds(const uint32_t modmask, const SP
|
||||
|
||||
if (!pressed) {
|
||||
// Require mods to be matching when the key was first pressed.
|
||||
if (key.modmaskAtPressTime != modmask && !k.ignoreMods) {
|
||||
if (key.modmaskAtPressTime != modmask && !k->ignoreMods) {
|
||||
// Handle properly `bindr` where a key is itself a bind mod for example:
|
||||
// "bindr = SUPER, SUPER_L, exec, $launcher".
|
||||
// This needs to be handled separately for the above case, because `key.modmaskAtPressTime` is set
|
||||
@@ -692,8 +709,8 @@ SDispatchResult CKeybindManager::handleKeybinds(const uint32_t modmask, const SP
|
||||
if (keycodeToModifier(key.keycode) == key.modmaskAtPressTime)
|
||||
continue;
|
||||
|
||||
} else if (!k.release && !SPECIALDISPATCHER) {
|
||||
if (k.nonConsuming)
|
||||
} else if (!k->release && !SPECIALDISPATCHER) {
|
||||
if (k->nonConsuming)
|
||||
continue;
|
||||
|
||||
found = true; // suppress the event
|
||||
@@ -701,16 +718,25 @@ SDispatchResult CKeybindManager::handleKeybinds(const uint32_t modmask, const SP
|
||||
}
|
||||
}
|
||||
|
||||
const auto DISPATCHER = m_mDispatchers.find(k.mouse ? "mouse" : k.handler);
|
||||
if (k->longPress) {
|
||||
const auto PACTIVEKEEB = g_pSeatManager->keyboard.lock();
|
||||
|
||||
m_pLongPressTimer->updateTimeout(std::chrono::milliseconds(PACTIVEKEEB->repeatDelay));
|
||||
m_pLastLongPressKeybind = k;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto DISPATCHER = m_mDispatchers.find(k->mouse ? "mouse" : k->handler);
|
||||
|
||||
if (SPECIALTRIGGERED && !pressed)
|
||||
std::erase_if(m_vPressedSpecialBinds, [&](const auto& other) { return other == &k; });
|
||||
std::erase_if(m_vPressedSpecialBinds, [&](const auto& other) { return other == k; });
|
||||
else if (SPECIALDISPATCHER && pressed)
|
||||
m_vPressedSpecialBinds.push_back(&k);
|
||||
m_vPressedSpecialBinds.emplace_back(k);
|
||||
|
||||
// Should never happen, as we check in the ConfigManager, but oh well
|
||||
if (DISPATCHER == m_mDispatchers.end()) {
|
||||
Debug::log(ERR, "Invalid handler in a keybind! (handler {} does not exist)", k.handler);
|
||||
Debug::log(ERR, "Invalid handler in a keybind! (handler {} does not exist)", k->handler);
|
||||
} else {
|
||||
// call the dispatcher
|
||||
Debug::log(LOG, "Keybind triggered, calling dispatcher ({}, {}, {})", modmask, key.keyName, key.keysym);
|
||||
@@ -718,29 +744,27 @@ SDispatchResult CKeybindManager::handleKeybinds(const uint32_t modmask, const SP
|
||||
m_iPassPressed = (int)pressed;
|
||||
|
||||
// if the dispatchers says to pass event then we will
|
||||
if (k.handler == "mouse")
|
||||
res = DISPATCHER->second((pressed ? "1" : "0") + k.arg);
|
||||
if (k->handler == "mouse")
|
||||
res = DISPATCHER->second((pressed ? "1" : "0") + k->arg);
|
||||
else
|
||||
res = DISPATCHER->second(k.arg);
|
||||
res = DISPATCHER->second(k->arg);
|
||||
|
||||
m_iPassPressed = -1;
|
||||
|
||||
if (k.handler == "submap") {
|
||||
if (k->handler == "submap") {
|
||||
found = true; // don't process keybinds on submap change.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (k.repeat) {
|
||||
m_pActiveKeybind = &k;
|
||||
m_pActiveKeybindEventSource = wl_event_loop_add_timer(g_pCompositor->m_sWLEventLoop, repeatKeyHandler, &m_pActiveKeybind);
|
||||
|
||||
if (k->repeat) {
|
||||
const auto PACTIVEKEEB = g_pSeatManager->keyboard.lock();
|
||||
|
||||
wl_event_source_timer_update(m_pActiveKeybindEventSource, PACTIVEKEEB->repeatDelay);
|
||||
m_vActiveKeybinds.emplace_back(k);
|
||||
m_pRepeatKeyTimer->updateTimeout(std::chrono::milliseconds(PACTIVEKEEB->repeatDelay));
|
||||
}
|
||||
|
||||
if (!k.nonConsuming)
|
||||
if (!k->nonConsuming)
|
||||
found = true;
|
||||
}
|
||||
|
||||
@@ -761,17 +785,17 @@ SDispatchResult CKeybindManager::handleKeybinds(const uint32_t modmask, const SP
|
||||
void CKeybindManager::shadowKeybinds(const xkb_keysym_t& doesntHave, const uint32_t doesntHaveCode) {
|
||||
// shadow disables keybinds after one has been triggered
|
||||
|
||||
for (auto& k : m_lKeybinds) {
|
||||
for (auto& k : m_vKeybinds) {
|
||||
|
||||
bool shadow = false;
|
||||
|
||||
if (k.handler == "global" || k.transparent)
|
||||
if (k->handler == "global" || k->transparent)
|
||||
continue; // can't be shadowed
|
||||
|
||||
if (k.multiKey && (mkBindMatches(k) == MK_FULL_MATCH))
|
||||
if (k->multiKey && (mkBindMatches(k) == MK_FULL_MATCH))
|
||||
shadow = true;
|
||||
else {
|
||||
const auto KBKEY = xkb_keysym_from_name(k.key.c_str(), XKB_KEYSYM_CASE_INSENSITIVE);
|
||||
const auto KBKEY = xkb_keysym_from_name(k->key.c_str(), XKB_KEYSYM_CASE_INSENSITIVE);
|
||||
const auto KBKEYUPPER = xkb_keysym_to_upper(KBKEY);
|
||||
|
||||
for (auto const& pk : m_dPressedKeys) {
|
||||
@@ -784,7 +808,7 @@ void CKeybindManager::shadowKeybinds(const xkb_keysym_t& doesntHave, const uint3
|
||||
}
|
||||
}
|
||||
|
||||
if (pk.keycode != 0 && pk.keycode == k.keycode) {
|
||||
if (pk.keycode != 0 && pk.keycode == k->keycode) {
|
||||
shadow = true;
|
||||
|
||||
if (pk.keycode == doesntHaveCode && doesntHaveCode != 0) {
|
||||
@@ -795,13 +819,13 @@ void CKeybindManager::shadowKeybinds(const xkb_keysym_t& doesntHave, const uint3
|
||||
}
|
||||
}
|
||||
|
||||
k.shadowed = shadow;
|
||||
k->shadowed = shadow;
|
||||
}
|
||||
}
|
||||
|
||||
bool CKeybindManager::handleVT(xkb_keysym_t keysym) {
|
||||
// Handles the CTRL+ALT+FX TTY keybinds
|
||||
if (!(keysym >= XKB_KEY_XF86Switch_VT_1 && keysym <= XKB_KEY_XF86Switch_VT_12))
|
||||
if (keysym < XKB_KEY_XF86Switch_VT_1 || keysym > XKB_KEY_XF86Switch_VT_12)
|
||||
return false;
|
||||
|
||||
// beyond this point, return true to not handle anything else.
|
||||
@@ -916,7 +940,7 @@ uint64_t CKeybindManager::spawnRawProc(std::string args, PHLWORKSPACE pInitialWo
|
||||
|
||||
sigset_t set;
|
||||
sigemptyset(&set);
|
||||
sigprocmask(SIG_SETMASK, &set, NULL);
|
||||
sigprocmask(SIG_SETMASK, &set, nullptr);
|
||||
|
||||
grandchild = fork();
|
||||
if (grandchild == 0) {
|
||||
@@ -942,7 +966,7 @@ uint64_t CKeybindManager::spawnRawProc(std::string args, PHLWORKSPACE pInitialWo
|
||||
read(socket[0], &grandchild, sizeof(grandchild));
|
||||
close(socket[0]);
|
||||
// clear child and leave grandchild to init
|
||||
waitpid(child, NULL, 0);
|
||||
waitpid(child, nullptr, 0);
|
||||
if (grandchild < 0) {
|
||||
Debug::log(LOG, "Fail to create the second fork");
|
||||
return 0;
|
||||
@@ -973,7 +997,7 @@ SDispatchResult CKeybindManager::kill(std::string args) {
|
||||
}
|
||||
|
||||
void CKeybindManager::clearKeybinds() {
|
||||
m_lKeybinds.clear();
|
||||
m_vKeybinds.clear();
|
||||
}
|
||||
|
||||
static SDispatchResult toggleActiveFloatingCore(std::string args, std::optional<bool> floatState) {
|
||||
@@ -1010,8 +1034,12 @@ static SDispatchResult toggleActiveFloatingCore(std::string args, std::optional<
|
||||
|
||||
g_pLayoutManager->getCurrentLayout()->changeWindowFloatingMode(PWINDOW);
|
||||
}
|
||||
g_pCompositor->updateWorkspaceWindows(PWINDOW->workspaceID());
|
||||
g_pCompositor->updateWorkspaceWindowData(PWINDOW->workspaceID());
|
||||
|
||||
if (PWINDOW->m_pWorkspace) {
|
||||
PWINDOW->m_pWorkspace->updateWindows();
|
||||
PWINDOW->m_pWorkspace->updateWindowData();
|
||||
}
|
||||
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PWINDOW->monitorID());
|
||||
g_pCompositor->updateAllWindowsAnimatedDecorationValues();
|
||||
|
||||
@@ -1174,12 +1202,12 @@ SDispatchResult CKeybindManager::changeworkspace(std::string args) {
|
||||
|
||||
const static auto PWARPONWORKSPACECHANGE = CConfigValue<Hyprlang::INT>("cursor:warp_on_change_workspace");
|
||||
|
||||
if (*PWARPONWORKSPACECHANGE) {
|
||||
if (*PWARPONWORKSPACECHANGE > 0) {
|
||||
auto PLAST = pWorkspaceToChangeTo->getLastFocusedWindow();
|
||||
auto HLSurface = CWLSurface::fromResource(g_pSeatManager->state.pointerFocus.lock());
|
||||
|
||||
if (PLAST && (!HLSurface || HLSurface->getWindow()))
|
||||
PLAST->warpCursor();
|
||||
PLAST->warpCursor(*PWARPONWORKSPACECHANGE == 2);
|
||||
}
|
||||
|
||||
return {};
|
||||
@@ -1218,15 +1246,15 @@ SDispatchResult CKeybindManager::fullscreenStateActive(std::string args) {
|
||||
clientMode = std::stoi(ARGS[1]);
|
||||
} catch (std::exception& e) { clientMode = -1; }
|
||||
|
||||
const sFullscreenState STATE = sFullscreenState{.internal = (internalMode != -1 ? (eFullscreenMode)internalMode : PWINDOW->m_sFullscreenState.internal),
|
||||
const SFullscreenState STATE = SFullscreenState{.internal = (internalMode != -1 ? (eFullscreenMode)internalMode : PWINDOW->m_sFullscreenState.internal),
|
||||
.client = (clientMode != -1 ? (eFullscreenMode)clientMode : PWINDOW->m_sFullscreenState.client)};
|
||||
|
||||
if (internalMode != -1 && clientMode != -1 && PWINDOW->m_sFullscreenState.internal == STATE.internal && PWINDOW->m_sFullscreenState.client == STATE.client)
|
||||
g_pCompositor->setWindowFullscreenState(PWINDOW, sFullscreenState{.internal = FSMODE_NONE, .client = FSMODE_NONE});
|
||||
g_pCompositor->setWindowFullscreenState(PWINDOW, SFullscreenState{.internal = FSMODE_NONE, .client = FSMODE_NONE});
|
||||
else if (internalMode != -1 && clientMode == -1 && PWINDOW->m_sFullscreenState.internal == STATE.internal)
|
||||
g_pCompositor->setWindowFullscreenState(PWINDOW, sFullscreenState{.internal = FSMODE_NONE, .client = PWINDOW->m_sFullscreenState.client});
|
||||
g_pCompositor->setWindowFullscreenState(PWINDOW, SFullscreenState{.internal = FSMODE_NONE, .client = PWINDOW->m_sFullscreenState.client});
|
||||
else if (internalMode == -1 && clientMode != -1 && PWINDOW->m_sFullscreenState.client == STATE.client)
|
||||
g_pCompositor->setWindowFullscreenState(PWINDOW, sFullscreenState{.internal = PWINDOW->m_sFullscreenState.internal, .client = FSMODE_NONE});
|
||||
g_pCompositor->setWindowFullscreenState(PWINDOW, SFullscreenState{.internal = PWINDOW->m_sFullscreenState.internal, .client = FSMODE_NONE});
|
||||
else
|
||||
g_pCompositor->setWindowFullscreenState(PWINDOW, STATE);
|
||||
|
||||
@@ -1279,7 +1307,7 @@ SDispatchResult CKeybindManager::moveActiveToWorkspace(std::string args) {
|
||||
g_pCompositor->moveWindowToWorkspaceSafe(PWINDOW, pWorkspace);
|
||||
}
|
||||
|
||||
POLDWS->m_pLastFocusedWindow = g_pCompositor->getFirstWindowOnWorkspace(POLDWS->m_iID);
|
||||
POLDWS->m_pLastFocusedWindow = POLDWS->getFirstWindow();
|
||||
|
||||
if (pWorkspace->m_bIsSpecialWorkspace)
|
||||
pMonitor->setSpecialWorkspace(pWorkspace);
|
||||
@@ -1346,6 +1374,7 @@ SDispatchResult CKeybindManager::moveActiveToWorkspaceSilent(std::string args) {
|
||||
SDispatchResult CKeybindManager::moveFocusTo(std::string args) {
|
||||
static auto PFULLCYCLE = CConfigValue<Hyprlang::INT>("binds:movefocus_cycles_fullscreen");
|
||||
static auto PMONITORFALLBACK = CConfigValue<Hyprlang::INT>("binds:window_direction_monitor_fallback");
|
||||
static auto PGROUPCYCLE = CConfigValue<Hyprlang::INT>("binds:movefocus_cycles_groupfirst");
|
||||
char arg = args[0];
|
||||
|
||||
if (!isDirection(args)) {
|
||||
@@ -1365,6 +1394,21 @@ SDispatchResult CKeybindManager::moveFocusTo(std::string args) {
|
||||
(arg == 'd' || arg == 'b' || arg == 'r' ? g_pCompositor->getNextWindowOnWorkspace(PLASTWINDOW, true) : g_pCompositor->getPrevWindowOnWorkspace(PLASTWINDOW, true)) :
|
||||
g_pCompositor->getWindowInDirection(PLASTWINDOW, arg);
|
||||
|
||||
// Prioritize focus change within groups if the window is a part of it.
|
||||
if (*PGROUPCYCLE) {
|
||||
if (!PLASTWINDOW->m_sGroupData.pNextWindow.expired()) {
|
||||
if (arg == 'l' && PLASTWINDOW != PLASTWINDOW->getGroupHead()) {
|
||||
PLASTWINDOW->setGroupCurrent(PLASTWINDOW->getGroupPrevious());
|
||||
return {};
|
||||
}
|
||||
|
||||
else if (arg == 'r' && PLASTWINDOW != PLASTWINDOW->getGroupTail()) {
|
||||
PLASTWINDOW->setGroupCurrent(PLASTWINDOW->m_sGroupData.pNextWindow.lock());
|
||||
return {};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Found window in direction, switch to it
|
||||
if (PWINDOWTOCHANGETO) {
|
||||
switchToWindow(PWINDOWTOCHANGETO);
|
||||
@@ -1732,7 +1776,7 @@ SDispatchResult CKeybindManager::workspaceOpt(std::string args) {
|
||||
// apply
|
||||
|
||||
// we make a copy because changeWindowFloatingMode might invalidate the iterator
|
||||
std::deque<PHLWINDOW> ptrs;
|
||||
std::vector<PHLWINDOW> ptrs;
|
||||
for (auto const& w : g_pCompositor->m_vWindows)
|
||||
ptrs.push_back(w);
|
||||
|
||||
@@ -1773,13 +1817,17 @@ SDispatchResult CKeybindManager::renameWorkspace(std::string args) {
|
||||
if (FIRSTSPACEPOS != std::string::npos) {
|
||||
int workspace = std::stoi(args.substr(0, FIRSTSPACEPOS));
|
||||
std::string name = args.substr(FIRSTSPACEPOS + 1);
|
||||
g_pCompositor->renameWorkspace(workspace, name);
|
||||
} else {
|
||||
g_pCompositor->renameWorkspace(std::stoi(args), "");
|
||||
}
|
||||
if (const auto& PWS = g_pCompositor->getWorkspaceByID(workspace); PWS)
|
||||
PWS->rename(name);
|
||||
else
|
||||
return {.success = false, .error = "No such workspace"};
|
||||
} else if (const auto& PWS = g_pCompositor->getWorkspaceByID(std::stoi(args)); PWS)
|
||||
PWS->rename("");
|
||||
else
|
||||
return {.success = false, .error = "No such workspace"};
|
||||
} catch (std::exception& e) {
|
||||
Debug::log(ERR, "Invalid arg in renameWorkspace, expected numeric id only or a numeric id and string name. \"{}\": \"{}\"", args, e.what());
|
||||
return {.success = false, .error = std::format("Invalid arg in renameWorkspace, expected numeric id only or a numeric id and string name. \"{}\": \"{}\"", args, e.what())};
|
||||
Debug::log(ERR, R"(Invalid arg in renameWorkspace, expected numeric id only or a numeric id and string name. "{}": "{}")", args, e.what());
|
||||
return {.success = false, .error = std::format(R"(Invalid arg in renameWorkspace, expected numeric id only or a numeric id and string name. "{}": "{}")", args, e.what())};
|
||||
}
|
||||
|
||||
return {};
|
||||
@@ -1849,7 +1897,7 @@ SDispatchResult CKeybindManager::moveWorkspaceToMonitor(std::string args) {
|
||||
}
|
||||
|
||||
SDispatchResult CKeybindManager::focusWorkspaceOnCurrentMonitor(std::string args) {
|
||||
auto workspaceID = getWorkspaceIDNameFromString(args).id;
|
||||
auto [workspaceID, workspaceName] = getWorkspaceIDNameFromString(args);
|
||||
if (workspaceID == WORKSPACE_INVALID) {
|
||||
Debug::log(ERR, "focusWorkspaceOnCurrentMonitor invalid workspace!");
|
||||
return {.success = false, .error = "focusWorkspaceOnCurrentMonitor invalid workspace!"};
|
||||
@@ -1865,7 +1913,7 @@ SDispatchResult CKeybindManager::focusWorkspaceOnCurrentMonitor(std::string args
|
||||
auto pWorkspace = g_pCompositor->getWorkspaceByID(workspaceID);
|
||||
|
||||
if (!pWorkspace) {
|
||||
pWorkspace = g_pCompositor->createNewWorkspace(workspaceID, PCURRMONITOR->ID);
|
||||
pWorkspace = g_pCompositor->createNewWorkspace(workspaceID, PCURRMONITOR->ID, workspaceName);
|
||||
// we can skip the moving, since it's already on the current monitor
|
||||
changeworkspace(pWorkspace->getConfigName());
|
||||
return {};
|
||||
@@ -2043,9 +2091,9 @@ SDispatchResult CKeybindManager::circleNext(std::string arg) {
|
||||
|
||||
if (g_pCompositor->m_pLastWindow.expired()) {
|
||||
// if we have a clear focus, find the first window and get the next focusable.
|
||||
if (g_pCompositor->getWindowsOnWorkspace(g_pCompositor->m_pLastMonitor->activeWorkspaceID()) > 0) {
|
||||
const auto PWINDOW = g_pCompositor->getFirstWindowOnWorkspace(g_pCompositor->m_pLastMonitor->activeWorkspaceID());
|
||||
|
||||
const auto PWS = g_pCompositor->m_pLastMonitor->activeWorkspace;
|
||||
if (PWS && PWS->getWindows() > 0) {
|
||||
const auto PWINDOW = PWS->getFirstWindow();
|
||||
switchToWindow(PWINDOW);
|
||||
}
|
||||
|
||||
@@ -2091,7 +2139,7 @@ SDispatchResult CKeybindManager::focusWindow(std::string regexp) {
|
||||
}
|
||||
|
||||
if (PWORKSPACE->m_bHasFullscreenWindow) {
|
||||
const auto FSWINDOW = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID);
|
||||
const auto FSWINDOW = PWORKSPACE->getFullscreenWindow();
|
||||
const auto FSMODE = PWORKSPACE->m_efFullscreenMode;
|
||||
|
||||
if (PWINDOW->m_bIsFloating) {
|
||||
@@ -2110,6 +2158,10 @@ SDispatchResult CKeybindManager::focusWindow(std::string regexp) {
|
||||
|
||||
if (FSWINDOW != PWINDOW && !PWINDOW->m_bPinned)
|
||||
g_pCompositor->setWindowFullscreenClient(PWINDOW, FSMODE);
|
||||
|
||||
// warp the position + size animation, otherwise it looks weird.
|
||||
PWINDOW->m_vRealPosition.warp();
|
||||
PWINDOW->m_vRealSize.warp();
|
||||
}
|
||||
} else
|
||||
g_pCompositor->focusWindow(PWINDOW);
|
||||
@@ -2147,8 +2199,8 @@ SDispatchResult CKeybindManager::setSubmap(std::string submap) {
|
||||
return {};
|
||||
}
|
||||
|
||||
for (auto const& k : g_pKeybindManager->m_lKeybinds) {
|
||||
if (k.submap == submap) {
|
||||
for (const auto& k : g_pKeybindManager->m_vKeybinds) {
|
||||
if (k->submap == submap) {
|
||||
m_szCurrentSelectedSubmap = submap;
|
||||
Debug::log(LOG, "Changed keybind submap to {}", submap);
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"submap", submap});
|
||||
@@ -2248,7 +2300,7 @@ SDispatchResult CKeybindManager::sendshortcut(std::string args) {
|
||||
const auto MOD = g_pKeybindManager->stringToModMask(ARGS[0]);
|
||||
const auto KEY = ARGS[1];
|
||||
uint32_t keycode = 0;
|
||||
bool isMouse = 0;
|
||||
bool isMouse = false;
|
||||
|
||||
// similar to parseKey in ConfigManager
|
||||
if (isNumber(KEY) && std::stoi(KEY) > 9)
|
||||
@@ -2257,7 +2309,7 @@ SDispatchResult CKeybindManager::sendshortcut(std::string args) {
|
||||
keycode = std::stoi(KEY.substr(5));
|
||||
else if (KEY.compare(0, 6, "mouse:") == 0 && isNumber(KEY.substr(6))) {
|
||||
keycode = std::stoi(KEY.substr(6));
|
||||
isMouse = 1;
|
||||
isMouse = true;
|
||||
if (keycode < 272) {
|
||||
Debug::log(ERR, "sendshortcut: invalid mouse button");
|
||||
return {.success = false, .error = "sendshortcut: invalid mouse button"};
|
||||
@@ -2605,9 +2657,9 @@ SDispatchResult CKeybindManager::alterZOrder(std::string args) {
|
||||
}
|
||||
|
||||
if (POSITION == "top")
|
||||
g_pCompositor->changeWindowZOrder(PWINDOW, 1);
|
||||
g_pCompositor->changeWindowZOrder(PWINDOW, true);
|
||||
else if (POSITION == "bottom")
|
||||
g_pCompositor->changeWindowZOrder(PWINDOW, 0);
|
||||
g_pCompositor->changeWindowZOrder(PWINDOW, false);
|
||||
else {
|
||||
Debug::log(ERR, "alterZOrder: bad position: {}", POSITION);
|
||||
return {.success = false, .error = "alterZOrder: bad position: {}"};
|
||||
@@ -2892,6 +2944,9 @@ SDispatchResult CKeybindManager::event(std::string args) {
|
||||
return {};
|
||||
}
|
||||
|
||||
#include <utility>
|
||||
#include <type_traits>
|
||||
|
||||
SDispatchResult CKeybindManager::setProp(std::string args) {
|
||||
CVarList vars(args, 3, ' ');
|
||||
|
||||
@@ -2930,13 +2985,13 @@ SDispatchResult CKeybindManager::setProp(std::string args) {
|
||||
CWindowOverridableVar(SAlphaValue{std::stof(VAL), PWINDOW->m_sWindowData.alphaFullscreen.valueOrDefault().m_bOverride}, PRIORITY_SET_PROP);
|
||||
} else if (PROP == "alphaoverride") {
|
||||
PWINDOW->m_sWindowData.alpha =
|
||||
CWindowOverridableVar(SAlphaValue{PWINDOW->m_sWindowData.alpha.valueOrDefault().m_fAlpha, (bool)configStringToInt(VAL)}, PRIORITY_SET_PROP);
|
||||
CWindowOverridableVar(SAlphaValue{PWINDOW->m_sWindowData.alpha.valueOrDefault().m_fAlpha, (bool)configStringToInt(VAL).value_or(0)}, PRIORITY_SET_PROP);
|
||||
} else if (PROP == "alphainactiveoverride") {
|
||||
PWINDOW->m_sWindowData.alphaInactive =
|
||||
CWindowOverridableVar(SAlphaValue{PWINDOW->m_sWindowData.alphaInactive.valueOrDefault().m_fAlpha, (bool)configStringToInt(VAL)}, PRIORITY_SET_PROP);
|
||||
CWindowOverridableVar(SAlphaValue{PWINDOW->m_sWindowData.alphaInactive.valueOrDefault().m_fAlpha, (bool)configStringToInt(VAL).value_or(0)}, PRIORITY_SET_PROP);
|
||||
} else if (PROP == "alphafullscreenoverride") {
|
||||
PWINDOW->m_sWindowData.alphaFullscreen =
|
||||
CWindowOverridableVar(SAlphaValue{PWINDOW->m_sWindowData.alphaFullscreen.valueOrDefault().m_fAlpha, (bool)configStringToInt(VAL)}, PRIORITY_SET_PROP);
|
||||
CWindowOverridableVar(SAlphaValue{PWINDOW->m_sWindowData.alphaFullscreen.valueOrDefault().m_fAlpha, (bool)configStringToInt(VAL).value_or(0)}, PRIORITY_SET_PROP);
|
||||
} else if (PROP == "activebordercolor" || PROP == "inactivebordercolor") {
|
||||
CGradientValueData colorData = {};
|
||||
if (vars.size() > 4) {
|
||||
@@ -2945,10 +3000,18 @@ SDispatchResult CKeybindManager::setProp(std::string args) {
|
||||
if (TOKEN.ends_with("deg"))
|
||||
colorData.m_fAngle = std::stoi(TOKEN.substr(0, TOKEN.size() - 3)) * (PI / 180.0);
|
||||
else
|
||||
colorData.m_vColors.push_back(configStringToInt(TOKEN));
|
||||
configStringToInt(TOKEN).and_then([&colorData](const auto& e) {
|
||||
colorData.m_vColors.push_back(e);
|
||||
return std::invoke_result_t<decltype(::configStringToInt), const std::string&>(1);
|
||||
});
|
||||
}
|
||||
} else if (VAL != "-1")
|
||||
colorData.m_vColors.push_back(configStringToInt(VAL));
|
||||
configStringToInt(VAL).and_then([&colorData](const auto& e) {
|
||||
colorData.m_vColors.push_back(e);
|
||||
return std::invoke_result_t<decltype(::configStringToInt), const std::string&>(1);
|
||||
});
|
||||
|
||||
colorData.updateColorsOk();
|
||||
|
||||
if (PROP == "activebordercolor")
|
||||
PWINDOW->m_sWindowData.activeBorderColor = CWindowOverridableVar(colorData, PRIORITY_SET_PROP);
|
||||
@@ -2961,15 +3024,21 @@ SDispatchResult CKeybindManager::setProp(std::string args) {
|
||||
else if (VAL == "unset")
|
||||
pWindowDataElement->unset(PRIORITY_SET_PROP);
|
||||
else
|
||||
*pWindowDataElement = CWindowOverridableVar((bool)configStringToInt(VAL), PRIORITY_SET_PROP);
|
||||
*pWindowDataElement = CWindowOverridableVar((bool)configStringToInt(VAL).value_or(0), PRIORITY_SET_PROP);
|
||||
} else if (auto search = g_pConfigManager->miWindowProperties.find(PROP); search != g_pConfigManager->miWindowProperties.end()) {
|
||||
if (VAL == "unset")
|
||||
search->second(PWINDOW)->unset(PRIORITY_SET_PROP);
|
||||
else
|
||||
*(search->second(PWINDOW)) = CWindowOverridableVar((int)configStringToInt(VAL), PRIORITY_SET_PROP);
|
||||
} else {
|
||||
else if (const auto V = configStringToInt(VAL); V)
|
||||
*(search->second(PWINDOW)) = CWindowOverridableVar((int)*V, PRIORITY_SET_PROP);
|
||||
} else if (auto search = g_pConfigManager->mfWindowProperties.find(PROP); search != g_pConfigManager->mfWindowProperties.end()) {
|
||||
if (VAL == "unset")
|
||||
search->second(PWINDOW)->unset(PRIORITY_SET_PROP);
|
||||
else {
|
||||
const auto V = std::stof(VAL);
|
||||
*(search->second(PWINDOW)) = CWindowOverridableVar(V, PRIORITY_SET_PROP);
|
||||
}
|
||||
} else
|
||||
return {.success = false, .error = "Prop not found"};
|
||||
}
|
||||
} catch (std::exception& e) { return {.success = false, .error = std::format("Error parsing prop value: {}", std::string(e.what()))}; }
|
||||
|
||||
g_pCompositor->updateAllWindowsAnimatedDecorationValues();
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user