mirror of
https://github.com/hyprwm/Hyprland.git
synced 2025-08-15 20:13:49 -07:00
Compare commits
25 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
882f7ad7d2 | ||
|
3822673c05 | ||
|
bdbfa93371 | ||
|
f827690983 | ||
|
ff8b5b70fa | ||
|
3236566939 | ||
|
dd64757602 | ||
|
047ea02820 | ||
|
c8eec1916d | ||
|
c062fd2985 | ||
|
f04d94aa13 | ||
|
75dff7205f | ||
|
48817b97f5 | ||
|
664da71d10 | ||
|
a285722bc8 | ||
|
bdee557d15 | ||
|
901271fa8b | ||
|
fa61042288 | ||
|
778508e39e | ||
|
762bbf5857 | ||
|
c68653d7c4 | ||
|
56540f5bd8 | ||
|
017f322532 | ||
|
a7d7df5c4b | ||
|
0d06f287d0 |
1
.github/actions/setup_base/action.yml
vendored
1
.github/actions/setup_base/action.yml
vendored
@@ -35,7 +35,6 @@ runs:
|
||||
libinput \
|
||||
libjxl \
|
||||
libliftoff \
|
||||
libspng \
|
||||
libwebp \
|
||||
libxcursor \
|
||||
libxcvt \
|
||||
|
26
.github/workflows/ci.yaml
vendored
26
.github/workflows/ci.yaml
vendored
@@ -21,7 +21,7 @@ jobs:
|
||||
|
||||
- name: Build Hyprland
|
||||
run: |
|
||||
CFLAGS=-Werror CXXFLAGS=-Werror make all
|
||||
make all
|
||||
|
||||
- name: Compress and package artifacts
|
||||
run: |
|
||||
@@ -127,3 +127,27 @@ jobs:
|
||||
|
||||
- name: clang-format check
|
||||
run: ninja -C build clang-format-check
|
||||
|
||||
- name: clang-format apply
|
||||
if: ${{ failure() && github.event_name == 'pull_request' }}
|
||||
run: ninja -C build clang-format
|
||||
|
||||
- name: Create patch
|
||||
if: ${{ failure() && github.event_name == 'pull_request' }}
|
||||
run: |
|
||||
echo 'Please fix the formatting issues by running [`clang-format`](https://wiki.hyprland.org/Contributing-and-Debugging/PR-Guidelines/#code-style), or directly apply this patch:' > clang-format.patch
|
||||
echo '<details>' >> clang-format.patch
|
||||
echo '<summary>clang-format.patch</summary>' >> clang-format.patch
|
||||
echo >> clang-format.patch
|
||||
echo '```diff' >> clang-format.patch
|
||||
git diff >> clang-format.patch
|
||||
echo '```' >> clang-format.patch
|
||||
echo >> clang-format.patch
|
||||
echo '</details>' >> clang-format.patch
|
||||
|
||||
- name: Comment patch
|
||||
if: ${{ failure() && github.event_name == 'pull_request' }}
|
||||
uses: mshick/add-pr-comment@v2
|
||||
with:
|
||||
message-path: |
|
||||
clang-format.patch
|
||||
|
48
.github/workflows/clang-format.yml
vendored
48
.github/workflows/clang-format.yml
vendored
@@ -1,48 +0,0 @@
|
||||
name: clang-format
|
||||
on: pull_request_target
|
||||
jobs:
|
||||
clang-format:
|
||||
permissions: write-all
|
||||
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork
|
||||
name: "Code Style (Arch)"
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: archlinux
|
||||
steps:
|
||||
- name: Checkout repository actions
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
sparse-checkout: .github/actions
|
||||
|
||||
- name: Setup base
|
||||
uses: ./.github/actions/setup_base
|
||||
|
||||
- name: Configure
|
||||
run: meson setup build -Ddefault_library=static
|
||||
|
||||
- name: clang-format check
|
||||
run: ninja -C build clang-format-check
|
||||
|
||||
- name: clang-format apply
|
||||
if: ${{ failure() && github.event_name == 'pull_request' }}
|
||||
run: ninja -C build clang-format
|
||||
|
||||
- name: Create patch
|
||||
if: ${{ failure() && github.event_name == 'pull_request' }}
|
||||
run: |
|
||||
echo 'Please fix the formatting issues by running [`clang-format`](https://wiki.hyprland.org/Contributing-and-Debugging/PR-Guidelines/#code-style), or directly apply this patch:' > clang-format.patch
|
||||
echo '<details>' >> clang-format.patch
|
||||
echo '<summary>clang-format.patch</summary>' >> clang-format.patch
|
||||
echo >> clang-format.patch
|
||||
echo '```diff' >> clang-format.patch
|
||||
git diff >> clang-format.patch
|
||||
echo '```' >> clang-format.patch
|
||||
echo >> clang-format.patch
|
||||
echo '</details>' >> clang-format.patch
|
||||
|
||||
- name: Comment patch
|
||||
if: ${{ failure() && github.event_name == 'pull_request' }}
|
||||
uses: mshick/add-pr-comment@v2
|
||||
with:
|
||||
message-path: |
|
||||
clang-format.patch
|
1
.github/workflows/nix-build.yml
vendored
1
.github/workflows/nix-build.yml
vendored
@@ -19,6 +19,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: DeterminateSystems/nix-installer-action@main
|
||||
- uses: DeterminateSystems/magic-nix-cache-action@main
|
||||
|
||||
- uses: cachix/cachix-action@v15
|
||||
with:
|
||||
|
@@ -77,7 +77,6 @@ add_compile_definitions(HYPRLAND_VERSION="${HYPRLAND_VERSION}")
|
||||
include_directories(. "src/" "protocols/")
|
||||
|
||||
set(CMAKE_CXX_STANDARD 26)
|
||||
set(CXX_STANDARD_REQUIRED ON)
|
||||
add_compile_options(
|
||||
-Wall
|
||||
-Wextra
|
||||
@@ -102,21 +101,13 @@ else()
|
||||
endif()
|
||||
find_package(OpenGL REQUIRED COMPONENTS ${GLES_VERSION})
|
||||
|
||||
pkg_check_modules(aquamarine_dep REQUIRED IMPORTED_TARGET aquamarine>=0.8.0)
|
||||
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.5.1)
|
||||
pkg_check_modules(hyprutils_dep REQUIRED IMPORTED_TARGET hyprutils>=0.5.0)
|
||||
pkg_check_modules(hyprgraphics_dep REQUIRED IMPORTED_TARGET hyprgraphics>=0.1.1)
|
||||
|
||||
string(REPLACE "." ";" AQ_VERSION_LIST ${aquamarine_dep_VERSION})
|
||||
list(GET AQ_VERSION_LIST 0 AQ_VERSION_MAJOR)
|
||||
list(GET AQ_VERSION_LIST 1 AQ_VERSION_MINOR)
|
||||
list(GET AQ_VERSION_LIST 2 AQ_VERSION_PATCH)
|
||||
|
||||
add_compile_definitions(AQUAMARINE_VERSION="${aquamarine_dep_VERSION}")
|
||||
add_compile_definitions(AQUAMARINE_VERSION_MAJOR=${AQ_VERSION_MAJOR})
|
||||
add_compile_definitions(AQUAMARINE_VERSION_MINOR=${AQ_VERSION_MINOR})
|
||||
add_compile_definitions(AQUAMARINE_VERSION_PATCH=${AQ_VERSION_PATCH})
|
||||
add_compile_definitions(HYPRLANG_VERSION="${hyprlang_dep_VERSION}")
|
||||
add_compile_definitions(HYPRUTILS_VERSION="${hyprutils_dep_VERSION}")
|
||||
add_compile_definitions(HYPRCURSOR_VERSION="${hyprcursor_dep_VERSION}")
|
||||
@@ -129,7 +120,7 @@ pkg_check_modules(
|
||||
xkbcommon
|
||||
uuid
|
||||
wayland-server>=1.22.90
|
||||
wayland-protocols>=1.41
|
||||
wayland-protocols
|
||||
cairo
|
||||
pango
|
||||
pangocairo
|
||||
@@ -313,7 +304,7 @@ endfunction()
|
||||
|
||||
target_link_libraries(Hyprland OpenGL::EGL OpenGL::GL Threads::Threads)
|
||||
|
||||
pkg_check_modules(hyprland_protocols_dep hyprland-protocols>=0.6.2)
|
||||
pkg_check_modules(hyprland_protocols_dep hyprland-protocols>=0.6.0)
|
||||
if(hyprland_protocols_dep_FOUND)
|
||||
pkg_get_variable(HYPRLAND_PROTOCOLS hyprland-protocols pkgdatadir)
|
||||
message(STATUS "hyprland-protocols dependency set to ${HYPRLAND_PROTOCOLS}")
|
||||
@@ -377,8 +368,6 @@ protocolnew("staging/linux-drm-syncobj" "linux-drm-syncobj-v1" false)
|
||||
protocolnew("staging/xdg-dialog" "xdg-dialog-v1" false)
|
||||
protocolnew("staging/single-pixel-buffer" "single-pixel-buffer-v1" false)
|
||||
protocolnew("staging/security-context" "security-context-v1" false)
|
||||
protocolnew("staging/content-type" "content-type-v1" false)
|
||||
protocolnew("staging/color-management" "color-management-v1" false)
|
||||
|
||||
protocolwayland()
|
||||
|
||||
@@ -444,5 +433,4 @@ install(
|
||||
DIRECTORY ${HEADERS_SRC}
|
||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/hyprland
|
||||
FILES_MATCHING
|
||||
PATTERN "*.h*"
|
||||
PATTERN "*.frag")
|
||||
PATTERN "*.h*")
|
||||
|
@@ -139,10 +139,10 @@ animations {
|
||||
# uncomment all if you wish to use that.
|
||||
# workspace = w[tv1], gapsout:0, gapsin:0
|
||||
# workspace = f[1], gapsout:0, gapsin:0
|
||||
# windowrule = bordersize 0, floating:0, onworkspace:w[tv1]
|
||||
# windowrule = rounding 0, floating:0, onworkspace:w[tv1]
|
||||
# windowrule = bordersize 0, floating:0, onworkspace:f[1]
|
||||
# windowrule = rounding 0, floating:0, onworkspace:f[1]
|
||||
# windowrulev2 = bordersize 0, floating:0, onworkspace:w[tv1]
|
||||
# windowrulev2 = rounding 0, floating:0, onworkspace:w[tv1]
|
||||
# windowrulev2 = bordersize 0, floating:0, onworkspace:f[1]
|
||||
# windowrulev2 = rounding 0, floating:0, onworkspace:f[1]
|
||||
|
||||
# See https://wiki.hyprland.org/Configuring/Dwindle-Layout/ for more
|
||||
dwindle {
|
||||
@@ -276,11 +276,14 @@ bindl = , XF86AudioPrev, exec, playerctl previous
|
||||
# See https://wiki.hyprland.org/Configuring/Window-Rules/ for more
|
||||
# See https://wiki.hyprland.org/Configuring/Workspace-Rules/ for workspace rules
|
||||
|
||||
# Example windowrule
|
||||
# windowrule = float,class:^(kitty)$,title:^(kitty)$
|
||||
# Example windowrule v1
|
||||
# windowrule = float, ^(kitty)$
|
||||
|
||||
# Example windowrule v2
|
||||
# windowrulev2 = float,class:^(kitty)$,title:^(kitty)$
|
||||
|
||||
# Ignore maximize requests from apps. You'll probably like this.
|
||||
windowrule = suppressevent maximize, class:.*
|
||||
windowrulev2 = suppressevent maximize, class:.*
|
||||
|
||||
# Fix some dragging issues with XWayland
|
||||
windowrule = nofocus,class:^$,title:^$,xwayland:1,floating:1,fullscreen:0,pinned:0
|
||||
windowrulev2 = nofocus,class:^$,title:^$,xwayland:1,floating:1,fullscreen:0,pinned:0
|
||||
|
137
flake.lock
generated
137
flake.lock
generated
@@ -16,11 +16,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1742213273,
|
||||
"narHash": "sha256-0l0vDb4anfsBu1rOs94bC73Hub+xEivgBAo6QXl2MmU=",
|
||||
"lastModified": 1737636397,
|
||||
"narHash": "sha256-F5MbBj3QVorycVSFE9qjuOTLtIQBqt2VWbXa0uwzm98=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "aquamarine",
|
||||
"rev": "484b732195cc53f4536ce4bd59a5c6402b1e7ccf",
|
||||
"rev": "7fe006981fae53e931f513026fc754e322f13145",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -79,11 +79,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1742215578,
|
||||
"narHash": "sha256-zfs71PXVVPEe56WEyNi2TJQPs0wabU4WAlq0XV7GcdE=",
|
||||
"lastModified": 1737634937,
|
||||
"narHash": "sha256-Ffw4ujFpi++6pPHe+gCBOfDgAoNlzVPZN6MReC1beu8=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "hyprcursor",
|
||||
"rev": "2fd36421c21aa87e2fe3bee11067540ae612f719",
|
||||
"rev": "9c5dd1f7c825ee47f72727ad0a4e16ca46a2688e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -105,11 +105,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1739049071,
|
||||
"narHash": "sha256-3+7TpXMrbsUXSwgr5VAKAnmkzMb6JO+Rvc9XRb5NMg4=",
|
||||
"lastModified": 1737634889,
|
||||
"narHash": "sha256-9JZE3KxcXOqZH9zs3UeadngDiK/yIACTiAR8HSA/TNI=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "hyprgraphics",
|
||||
"rev": "175c6b29b6ff82100539e7c4363a35a02c74dd73",
|
||||
"rev": "0d77b4895ad5f1bb3b0ee43103a5246c58b65591",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -128,11 +128,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1738422629,
|
||||
"narHash": "sha256-5v+bv75wJWvahyM2xcMTSNNxmV8a7hb01Eey5zYnBJw=",
|
||||
"lastModified": 1737556638,
|
||||
"narHash": "sha256-laKgI3mr2qz6tas/q3tuGPxMdsGhBi/w+HO+hO2f1AY=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "hyprland-protocols",
|
||||
"rev": "755aef8dab49d0fc4663c715fa4ad221b2aedaed",
|
||||
"rev": "4c75dd5c015c8a0e5a34c6d02a018a650f57feb5",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -143,10 +143,7 @@
|
||||
},
|
||||
"hyprland-qt-support": {
|
||||
"inputs": {
|
||||
"hyprlang": [
|
||||
"hyprland-qtutils",
|
||||
"hyprlang"
|
||||
],
|
||||
"hyprlang": "hyprlang",
|
||||
"nixpkgs": [
|
||||
"hyprland-qtutils",
|
||||
"nixpkgs"
|
||||
@@ -173,12 +170,7 @@
|
||||
"hyprland-qtutils": {
|
||||
"inputs": {
|
||||
"hyprland-qt-support": "hyprland-qt-support",
|
||||
"hyprlang": [
|
||||
"hyprlang"
|
||||
],
|
||||
"hyprutils": [
|
||||
"hyprland-qtutils",
|
||||
"hyprlang",
|
||||
"hyprutils"
|
||||
],
|
||||
"nixpkgs": [
|
||||
@@ -189,11 +181,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1739048983,
|
||||
"narHash": "sha256-REhTcXq4qs3B3cCDtLlYDz0GZvmsBSh947Ub6pQWGTQ=",
|
||||
"lastModified": 1737811848,
|
||||
"narHash": "sha256-WZ7LeiKHk5Y94MU5gHIWn0r8asWxYOvie4LqfCjVIZU=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "hyprland-qtutils",
|
||||
"rev": "3504a293c8f8db4127cb0f7cfc1a318ffb4316f8",
|
||||
"rev": "9c0831ff98856c0f312fcb8b57553fbe3dd34d5b",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -203,6 +195,34 @@
|
||||
}
|
||||
},
|
||||
"hyprlang": {
|
||||
"inputs": {
|
||||
"hyprutils": "hyprutils",
|
||||
"nixpkgs": [
|
||||
"hyprland-qtutils",
|
||||
"hyprland-qt-support",
|
||||
"nixpkgs"
|
||||
],
|
||||
"systems": [
|
||||
"hyprland-qtutils",
|
||||
"hyprland-qt-support",
|
||||
"systems"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1737634606,
|
||||
"narHash": "sha256-W7W87Cv6wqZ9PHegI6rH1+ve3zJPiyevMFf0/HwdbCQ=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "hyprlang",
|
||||
"rev": "f41271d35cc0f370d300413d756c2677f386af9d",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "hyprwm",
|
||||
"repo": "hyprlang",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"hyprlang_2": {
|
||||
"inputs": {
|
||||
"hyprutils": [
|
||||
"hyprutils"
|
||||
@@ -215,11 +235,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1741191527,
|
||||
"narHash": "sha256-kM+11Nch47Xwfgtw2EpRitJuORy4miwoMuRi5tyMBDY=",
|
||||
"lastModified": 1737634606,
|
||||
"narHash": "sha256-W7W87Cv6wqZ9PHegI6rH1+ve3zJPiyevMFf0/HwdbCQ=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "hyprlang",
|
||||
"rev": "72df3861f1197e41b078faa3e38eedd60e00018d",
|
||||
"rev": "f41271d35cc0f370d300413d756c2677f386af9d",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -229,6 +249,35 @@
|
||||
}
|
||||
},
|
||||
"hyprutils": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"hyprland-qtutils",
|
||||
"hyprland-qt-support",
|
||||
"hyprlang",
|
||||
"nixpkgs"
|
||||
],
|
||||
"systems": [
|
||||
"hyprland-qtutils",
|
||||
"hyprland-qt-support",
|
||||
"hyprlang",
|
||||
"systems"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1737632363,
|
||||
"narHash": "sha256-X9I8POSlHxBVjD0fiX1O2j7U9Zi1+4rIkrsyHP0uHXY=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "hyprutils",
|
||||
"rev": "006620eb29d54ea9086538891404c78563d1bae1",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "hyprwm",
|
||||
"repo": "hyprutils",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"hyprutils_2": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
@@ -238,11 +287,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1741534688,
|
||||
"narHash": "sha256-EV3945SnjOCuRVbGRghsWx/9D89FyshnSO1Q6/TuQ14=",
|
||||
"lastModified": 1737725508,
|
||||
"narHash": "sha256-jGmcPc6y/prg/4A8KGYqJ27nSPaProCMiFadaxNAKvA=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "hyprutils",
|
||||
"rev": "dd1f720cbc2dbb3c71167c9598045dd3261d27b3",
|
||||
"rev": "fb0c2d1de3d1ef7396d19c18ac09e12bd956929e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -261,11 +310,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1739870480,
|
||||
"narHash": "sha256-SiDN5BGxa/1hAsqhgJsS03C3t2QrLgBT8u+ENJ0Qzwc=",
|
||||
"lastModified": 1735493474,
|
||||
"narHash": "sha256-fktzv4NaqKm94VAkAoVqO/nqQlw+X0/tJJNAeCSfzK4=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "hyprwayland-scanner",
|
||||
"rev": "206367a08dc5ac4ba7ad31bdca391d098082e64b",
|
||||
"rev": "de913476b59ee88685fdc018e77b8f6637a2ae0b",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -276,11 +325,11 @@
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1742069588,
|
||||
"narHash": "sha256-C7jVfohcGzdZRF6DO+ybyG/sqpo1h6bZi9T56sxLy+k=",
|
||||
"lastModified": 1737632463,
|
||||
"narHash": "sha256-38J9QfeGSej341ouwzqf77WIHAScihAKCt8PQJ+NH28=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "c80f6a7e10b39afcc1894e02ef785b1ad0b0d7e5",
|
||||
"rev": "0aa475546ed21629c4f5bbf90e38c846a99ec9e9",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -299,11 +348,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1742058297,
|
||||
"narHash": "sha256-b4SZc6TkKw8WQQssbN5O2DaCEzmFfvSTPYHlx/SFW9Y=",
|
||||
"lastModified": 1737465171,
|
||||
"narHash": "sha256-R10v2hoJRLq8jcL4syVFag7nIGE7m13qO48wRIukWNg=",
|
||||
"owner": "cachix",
|
||||
"repo": "git-hooks.nix",
|
||||
"rev": "59f17850021620cd348ad2e9c0c64f4e6325ce2a",
|
||||
"rev": "9364dc02281ce2d37a1f55b6e51f7c0f65a75f17",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -319,8 +368,8 @@
|
||||
"hyprgraphics": "hyprgraphics",
|
||||
"hyprland-protocols": "hyprland-protocols",
|
||||
"hyprland-qtutils": "hyprland-qtutils",
|
||||
"hyprlang": "hyprlang",
|
||||
"hyprutils": "hyprutils",
|
||||
"hyprlang": "hyprlang_2",
|
||||
"hyprutils": "hyprutils_2",
|
||||
"hyprwayland-scanner": "hyprwayland-scanner",
|
||||
"nixpkgs": "nixpkgs",
|
||||
"pre-commit-hooks": "pre-commit-hooks",
|
||||
@@ -365,11 +414,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1741934139,
|
||||
"narHash": "sha256-ZhTcTH9FoeAtbPfWGrhkH7RjLJZ7GeF18nygLAMR+WE=",
|
||||
"lastModified": 1737634991,
|
||||
"narHash": "sha256-dBAnb7Kbnier30cA7AgxVSxxARmxKZ1vHZT33THSIr8=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "xdg-desktop-portal-hyprland",
|
||||
"rev": "150b0b6f52bb422a1b232a53698606fe0320dde0",
|
||||
"rev": "e09dfe2726c8008f983e45a0aa1a3b7416aaeb8a",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@@ -39,7 +39,7 @@
|
||||
url = "github:hyprwm/hyprland-qtutils";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
inputs.systems.follows = "systems";
|
||||
inputs.hyprlang.follows = "hyprlang";
|
||||
inputs.hyprutils.follows = "hyprutils";
|
||||
};
|
||||
|
||||
hyprlang = {
|
||||
@@ -157,11 +157,5 @@
|
||||
|
||||
nixosModules.default = import ./nix/module.nix inputs;
|
||||
homeManagerModules.default = import ./nix/hm-module.nix self;
|
||||
|
||||
# Hydra build jobs
|
||||
# Recent versions of Hydra can aggregate jobsets from 'hydraJobs' intead of a release.nix
|
||||
# or similar. Remember to filter large or incompatible attributes here. More eval jobs can
|
||||
# be added by merging, e.g., self.packages // self.devShells.
|
||||
hydraJobs = self.packages;
|
||||
};
|
||||
}
|
||||
|
@@ -22,7 +22,6 @@ commands:
|
||||
getoption <option> → Gets the config option status (values)
|
||||
globalshortcuts → Lists all global shortcuts
|
||||
hyprpaper ... → Issue a hyprpaper request
|
||||
hyprsunset ... → Issue a hyprsunset request
|
||||
instances → Lists all running instances of Hyprland with
|
||||
their info
|
||||
keyword <name> <value> → Issue a keyword to call a config keyword
|
||||
@@ -82,16 +81,6 @@ requests:
|
||||
flags:
|
||||
See 'hyprctl --help')#";
|
||||
|
||||
const std::string_view HYPRSUNSET_HELP = R"#(usage: hyprctl [flags] hyprsunset <request>
|
||||
|
||||
requests:
|
||||
temperature <temp> → Enable blue-light filter
|
||||
identity → Disable blue-light filter
|
||||
gamma <gamma> → Enable gamma filter
|
||||
|
||||
flags:
|
||||
See 'hyprctl --help')#";
|
||||
|
||||
const std::string_view NOTIFY_HELP = R"#(usage: hyprctl [flags] notify <icon> <time_ms> <color> <message...>
|
||||
|
||||
icon:
|
||||
|
@@ -12,17 +12,22 @@
|
||||
#include <sys/un.h>
|
||||
#include <pwd.h>
|
||||
#include <unistd.h>
|
||||
#include <ranges>
|
||||
#include <algorithm>
|
||||
#include <csignal>
|
||||
#include <format>
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <print>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <filesystem>
|
||||
#include <cstdarg>
|
||||
#include <sys/socket.h>
|
||||
#include <hyprutils/string/String.hpp>
|
||||
#include <cstring>
|
||||
using namespace Hyprutils::String;
|
||||
|
||||
#include "Strings.hpp"
|
||||
@@ -149,16 +154,8 @@ int rollingRead(const int socket) {
|
||||
int request(std::string arg, int minArgs = 0, bool needRoll = false) {
|
||||
const auto SERVERSOCKET = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
|
||||
if (SERVERSOCKET < 0) {
|
||||
log("Couldn't open a socket (1)");
|
||||
return 1;
|
||||
}
|
||||
|
||||
auto t = timeval{.tv_sec = 5, .tv_usec = 0};
|
||||
if (setsockopt(SERVERSOCKET, SOL_SOCKET, SO_RCVTIMEO, &t, sizeof(struct timeval)) < 0) {
|
||||
log("Couldn't set socket timeout (2)");
|
||||
return 2;
|
||||
}
|
||||
auto t = timeval{.tv_sec = 5, .tv_usec = 0};
|
||||
setsockopt(SERVERSOCKET, SOL_SOCKET, SO_RCVTIMEO, &t, sizeof(struct timeval));
|
||||
|
||||
const auto ARGS = std::count(arg.begin(), arg.end(), ' ');
|
||||
|
||||
@@ -167,9 +164,14 @@ int request(std::string arg, int minArgs = 0, bool needRoll = false) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (SERVERSOCKET < 0) {
|
||||
log("Couldn't open a socket (1)");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (instanceSignature.empty()) {
|
||||
log("HYPRLAND_INSTANCE_SIGNATURE was not set! (Is Hyprland running?) (3)");
|
||||
return 3;
|
||||
log("HYPRLAND_INSTANCE_SIGNATURE was not set! (Is Hyprland running?)");
|
||||
return 2;
|
||||
}
|
||||
|
||||
const std::string USERID = std::to_string(getUID());
|
||||
@@ -182,40 +184,39 @@ int request(std::string arg, int minArgs = 0, bool needRoll = false) {
|
||||
strncpy(serverAddress.sun_path, socketPath.c_str(), sizeof(serverAddress.sun_path) - 1);
|
||||
|
||||
if (connect(SERVERSOCKET, (sockaddr*)&serverAddress, SUN_LEN(&serverAddress)) < 0) {
|
||||
log("Couldn't connect to " + socketPath + ". (4)");
|
||||
return 4;
|
||||
log("Couldn't connect to " + socketPath + ". (3)");
|
||||
return 3;
|
||||
}
|
||||
|
||||
auto sizeWritten = write(SERVERSOCKET, arg.c_str(), arg.length());
|
||||
|
||||
if (sizeWritten < 0) {
|
||||
log("Couldn't write (5)");
|
||||
return 5;
|
||||
log("Couldn't write (4)");
|
||||
return 4;
|
||||
}
|
||||
|
||||
if (needRoll)
|
||||
return rollingRead(SERVERSOCKET);
|
||||
|
||||
std::string reply = "";
|
||||
constexpr size_t BUFFER_SIZE = 8192;
|
||||
char buffer[BUFFER_SIZE] = {0};
|
||||
std::string reply = "";
|
||||
char buffer[8192] = {0};
|
||||
|
||||
sizeWritten = read(SERVERSOCKET, buffer, BUFFER_SIZE);
|
||||
sizeWritten = read(SERVERSOCKET, buffer, 8192);
|
||||
|
||||
if (sizeWritten < 0) {
|
||||
if (errno == EWOULDBLOCK)
|
||||
log("Hyprland IPC didn't respond in time\n");
|
||||
log("Couldn't read (6)");
|
||||
return 6;
|
||||
log("Couldn't read (5)");
|
||||
return 5;
|
||||
}
|
||||
|
||||
reply += std::string(buffer, sizeWritten);
|
||||
|
||||
while (sizeWritten == BUFFER_SIZE) {
|
||||
sizeWritten = read(SERVERSOCKET, buffer, BUFFER_SIZE);
|
||||
while (sizeWritten == 8192) {
|
||||
sizeWritten = read(SERVERSOCKET, buffer, 8192);
|
||||
if (sizeWritten < 0) {
|
||||
log("Couldn't read (6)");
|
||||
return 6;
|
||||
log("Couldn't read (5)");
|
||||
return 5;
|
||||
}
|
||||
reply += std::string(buffer, sizeWritten);
|
||||
}
|
||||
@@ -227,7 +228,7 @@ int request(std::string arg, int minArgs = 0, bool needRoll = false) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int requestIPC(std::string filename, std::string arg) {
|
||||
int requestHyprpaper(std::string arg) {
|
||||
const auto SERVERSOCKET = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
|
||||
if (SERVERSOCKET < 0) {
|
||||
@@ -245,7 +246,7 @@ int requestIPC(std::string filename, std::string arg) {
|
||||
|
||||
const std::string USERID = std::to_string(getUID());
|
||||
|
||||
std::string socketPath = getRuntimeDir() + "/" + instanceSignature + "/" + filename;
|
||||
std::string socketPath = getRuntimeDir() + "/" + instanceSignature + "/.hyprpaper.sock";
|
||||
|
||||
strncpy(serverAddress.sun_path, socketPath.c_str(), sizeof(serverAddress.sun_path) - 1);
|
||||
|
||||
@@ -263,10 +264,10 @@ int requestIPC(std::string filename, std::string arg) {
|
||||
log("Couldn't write (4)");
|
||||
return 4;
|
||||
}
|
||||
constexpr size_t BUFFER_SIZE = 8192;
|
||||
char buffer[BUFFER_SIZE] = {0};
|
||||
|
||||
sizeWritten = read(SERVERSOCKET, buffer, BUFFER_SIZE);
|
||||
char buffer[8192] = {0};
|
||||
|
||||
sizeWritten = read(SERVERSOCKET, buffer, 8192);
|
||||
|
||||
if (sizeWritten < 0) {
|
||||
log("Couldn't read (5)");
|
||||
@@ -280,14 +281,6 @@ int requestIPC(std::string filename, std::string arg) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int requestHyprpaper(std::string arg) {
|
||||
return requestIPC(".hyprpaper.sock", arg);
|
||||
}
|
||||
|
||||
int requestHyprsunset(std::string arg) {
|
||||
return requestIPC(".hyprsunset.sock", arg);
|
||||
}
|
||||
|
||||
void batchRequest(std::string arg, bool json) {
|
||||
std::string commands = arg.substr(arg.find_first_of(' ') + 1);
|
||||
|
||||
@@ -392,8 +385,6 @@ int main(int argc, char** argv) {
|
||||
|
||||
if (cmd == "hyprpaper") {
|
||||
std::println("{}", HYPRPAPER_HELP);
|
||||
} else if (cmd == "hyprsunset") {
|
||||
std::println("{}", HYPRSUNSET_HELP);
|
||||
} else if (cmd == "notify") {
|
||||
std::println("{}", NOTIFY_HELP);
|
||||
} else if (cmd == "output") {
|
||||
@@ -475,8 +466,6 @@ int main(int argc, char** argv) {
|
||||
batchRequest(fullRequest, json);
|
||||
else if (fullRequest.contains("/hyprpaper"))
|
||||
exitStatus = requestHyprpaper(fullRequest);
|
||||
else if (fullRequest.contains("/hyprsunset"))
|
||||
exitStatus = requestHyprsunset(fullRequest);
|
||||
else if (fullRequest.contains("/switchxkblayout"))
|
||||
exitStatus = request(fullRequest, 2);
|
||||
else if (fullRequest.contains("/seterror"))
|
||||
|
@@ -463,9 +463,7 @@ bool CPluginManager::updateHeaders(bool force) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto& HL_URL = m_szCustomHlUrl.empty() ? "https://github.com/hyprwm/Hyprland" : m_szCustomHlUrl;
|
||||
|
||||
progress.printMessageAbove(statusString("!", Colors::YELLOW, "Cloning {}, this might take a moment.", HL_URL));
|
||||
progress.printMessageAbove(statusString("!", Colors::YELLOW, "Cloning https://github.com/hyprwm/Hyprland, this might take a moment."));
|
||||
|
||||
const bool bShallow = (HLVER.branch == "main") && !m_bNoShallow;
|
||||
|
||||
@@ -476,12 +474,12 @@ bool CPluginManager::updateHeaders(bool force) {
|
||||
if (m_bVerbose && bShallow)
|
||||
progress.printMessageAbove(verboseString("will shallow since: {}", SHALLOW_DATE));
|
||||
|
||||
std::string ret =
|
||||
execAndGet(std::format("cd {} && git clone --recursive {} hyprland-{}{}", getTempRoot(), HL_URL, 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(std::format("cd {} && git clone --recursive {} hyprland-{}", getTempRoot(), HL_URL, USERNAME));
|
||||
ret = execAndGet(std::format("cd {} && git clone --recursive https://github.com/hyprwm/hyprland hyprland-{}", getTempRoot(), USERNAME));
|
||||
}
|
||||
|
||||
if (!std::filesystem::exists(WORKINGDIR + "/.git")) {
|
||||
|
@@ -62,7 +62,6 @@ class CPluginManager {
|
||||
|
||||
bool m_bVerbose = false;
|
||||
bool m_bNoShallow = false;
|
||||
std::string m_szCustomHlUrl;
|
||||
|
||||
// will delete recursively if exists!!
|
||||
bool createSafeDirectory(const std::string& path);
|
||||
|
@@ -29,7 +29,6 @@ constexpr std::string_view HELP = R"#(┏ hyprpm, a Hyprland Plugin Manager
|
||||
┣ --verbose | -v → Enable too much logging
|
||||
┣ --force | -f → Force an operation ignoring checks (e.g. update -f)
|
||||
┣ --no-shallow | -s → Disable shallow cloning of Hyprland sources
|
||||
┣ --hl-url | → Pass a custom hyprland source url
|
||||
┗
|
||||
)#";
|
||||
|
||||
@@ -46,7 +45,6 @@ int main(int argc, char** argv, char** envp) {
|
||||
|
||||
std::vector<std::string> command;
|
||||
bool notify = false, notifyFail = false, verbose = false, force = false, noShallow = false;
|
||||
std::string customHlUrl;
|
||||
|
||||
for (int i = 1; i < argc; ++i) {
|
||||
if (ARGS[i].starts_with("-")) {
|
||||
@@ -61,13 +59,6 @@ int main(int argc, char** argv, char** envp) {
|
||||
verbose = true;
|
||||
} else if (ARGS[i] == "--no-shallow" || ARGS[i] == "-s") {
|
||||
noShallow = true;
|
||||
} else if (ARGS[i] == "--hl-url") {
|
||||
if (i + 1 >= argc) {
|
||||
std::println(stderr, "Missing argument for --hl-url");
|
||||
return 1;
|
||||
}
|
||||
customHlUrl = ARGS[i + 1];
|
||||
i++;
|
||||
} else if (ARGS[i] == "--force" || ARGS[i] == "-f") {
|
||||
force = true;
|
||||
std::println("{}", statusString("!", Colors::RED, "Using --force, I hope you know what you are doing."));
|
||||
@@ -75,8 +66,9 @@ int main(int argc, char** argv, char** envp) {
|
||||
std::println(stderr, "Unrecognized option {}", ARGS[i]);
|
||||
return 1;
|
||||
}
|
||||
} else
|
||||
} else {
|
||||
command.push_back(ARGS[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (command.empty()) {
|
||||
@@ -84,10 +76,9 @@ int main(int argc, char** argv, char** envp) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
g_pPluginManager = std::make_unique<CPluginManager>();
|
||||
g_pPluginManager->m_bVerbose = verbose;
|
||||
g_pPluginManager->m_bNoShallow = noShallow;
|
||||
g_pPluginManager->m_szCustomHlUrl = customHlUrl;
|
||||
g_pPluginManager = std::make_unique<CPluginManager>();
|
||||
g_pPluginManager->m_bVerbose = verbose;
|
||||
g_pPluginManager->m_bNoShallow = noShallow;
|
||||
|
||||
if (command[0] == "add") {
|
||||
if (command.size() < 2) {
|
||||
@@ -165,18 +156,15 @@ int main(int argc, char** argv, char** envp) {
|
||||
} else if (command[0] == "reload") {
|
||||
auto ret = g_pPluginManager->ensurePluginsLoadState(force);
|
||||
|
||||
if (ret != LOADSTATE_OK) {
|
||||
if (notify) {
|
||||
switch (ret) {
|
||||
case LOADSTATE_FAIL:
|
||||
case LOADSTATE_PARTIAL_FAIL: g_pPluginManager->notify(ICON_ERROR, 0, 10000, "[hyprpm] Failed to load plugins"); break;
|
||||
case LOADSTATE_HEADERS_OUTDATED:
|
||||
g_pPluginManager->notify(ICON_ERROR, 0, 10000, "[hyprpm] Failed to load plugins: Outdated headers. Please run hyprpm update manually.");
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
if (ret != LOADSTATE_OK && notify) {
|
||||
switch (ret) {
|
||||
case LOADSTATE_FAIL:
|
||||
case LOADSTATE_PARTIAL_FAIL: g_pPluginManager->notify(ICON_ERROR, 0, 10000, "[hyprpm] Failed to load plugins"); break;
|
||||
case LOADSTATE_HEADERS_OUTDATED:
|
||||
g_pPluginManager->notify(ICON_ERROR, 0, 10000, "[hyprpm] Failed to load plugins: Outdated headers. Please run hyprpm update manually.");
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
return 1;
|
||||
} else if (notify && !notifyFail) {
|
||||
g_pPluginManager->notify(ICON_OK, 0, 4000, "[hyprpm] Loaded plugins");
|
||||
|
@@ -31,16 +31,12 @@ if cpp_compiler.check_header('execinfo.h')
|
||||
add_project_arguments('-DHAS_EXECINFO', language: 'cpp')
|
||||
endif
|
||||
|
||||
aquamarine = dependency('aquamarine', version: '>=0.8.0')
|
||||
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')
|
||||
aquamarine_version_list = aquamarine.version().split('.')
|
||||
add_project_arguments(['-DAQUAMARINE_VERSION="@0@"'.format(aquamarine.version())], language: 'cpp')
|
||||
add_project_arguments(['-DAQUAMARINE_VERSION_MAJOR=@0@'.format(aquamarine_version_list.get(0))], language: 'cpp')
|
||||
add_project_arguments(['-DAQUAMARINE_VERSION_MINOR=@0@'.format(aquamarine_version_list.get(1))], language: 'cpp')
|
||||
add_project_arguments(['-DAQUAMARINE_VERSION_PATCH=@0@'.format(aquamarine_version_list.get(2))], 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')
|
||||
@@ -89,7 +85,7 @@ endif
|
||||
run_command('sh', '-c', 'scripts/generateVersion.sh', check: true)
|
||||
|
||||
# Install headers
|
||||
globber = run_command('find', 'src', '-name', '*.h*', '-o', '-name', '*.frag', check: true)
|
||||
globber = run_command('find', 'src', '-name', '*.h*', check: true)
|
||||
headers = globber.stdout().strip().split('\n')
|
||||
foreach file : headers
|
||||
install_headers(file, subdir: 'hyprland', preserve_path: true)
|
||||
|
@@ -26,7 +26,7 @@
|
||||
libinput,
|
||||
libxkbcommon,
|
||||
libuuid,
|
||||
libgbm,
|
||||
mesa,
|
||||
pango,
|
||||
pciutils,
|
||||
re2,
|
||||
@@ -130,7 +130,7 @@ in
|
||||
libinput
|
||||
libuuid
|
||||
libxkbcommon
|
||||
libgbm
|
||||
mesa
|
||||
pango
|
||||
pciutils
|
||||
re2
|
||||
@@ -155,7 +155,7 @@ in
|
||||
|
||||
mesonBuildType =
|
||||
if debug
|
||||
then "debug"
|
||||
then "debugoptimized"
|
||||
else "release";
|
||||
|
||||
mesonFlags = flatten [
|
||||
|
201
nix/lib.nix
201
nix/lib.nix
@@ -1,201 +0,0 @@
|
||||
lib: let
|
||||
inherit (lib)
|
||||
attrNames
|
||||
filterAttrs
|
||||
foldl
|
||||
generators
|
||||
partition
|
||||
;
|
||||
|
||||
inherit (lib.strings)
|
||||
concatMapStrings
|
||||
hasPrefix
|
||||
;
|
||||
|
||||
/**
|
||||
Convert a structured Nix attribute set into Hyprland's configuration format.
|
||||
|
||||
This function takes a nested attribute set and converts it into Hyprland-compatible
|
||||
configuration syntax, supporting top, bottom, and regular command sections.
|
||||
|
||||
Commands are flattened using the `flattenAttrs` function, and attributes are formatted as
|
||||
`key = value` pairs. Lists are expanded as duplicate keys to match Hyprland's expected format.
|
||||
|
||||
Configuration:
|
||||
|
||||
* `topCommandsPrefixes` - A list of prefixes to define **top** commands (default: `["$"]`).
|
||||
* `bottomCommandsPrefixes` - A list of prefixes to define **bottom** commands (default: `[]`).
|
||||
|
||||
Attention:
|
||||
|
||||
- The function ensures top commands appear **first** and bottom commands **last**.
|
||||
- The generated configuration is a **single string**, suitable for writing to a config file.
|
||||
- Lists are converted into multiple entries, ensuring compatibility with Hyprland.
|
||||
|
||||
# Inputs
|
||||
|
||||
Structured function argument:
|
||||
|
||||
: topCommandsPrefixes (optional, default: `["$"]`)
|
||||
: A list of prefixes that define **top** commands. Any key starting with one of these
|
||||
prefixes will be placed at the beginning of the configuration.
|
||||
: bottomCommandsPrefixes (optional, default: `[]`)
|
||||
: A list of prefixes that define **bottom** commands. Any key starting with one of these
|
||||
prefixes will be placed at the end of the configuration.
|
||||
|
||||
Value:
|
||||
|
||||
: The attribute set to be converted to Hyprland configuration format.
|
||||
|
||||
# Type
|
||||
|
||||
```
|
||||
toHyprlang :: AttrSet -> AttrSet -> String
|
||||
```
|
||||
|
||||
# Examples
|
||||
:::{.example}
|
||||
|
||||
```nix
|
||||
let
|
||||
config = {
|
||||
"$mod" = "SUPER";
|
||||
monitor = {
|
||||
"HDMI-A-1" = "1920x1080@60,0x0,1";
|
||||
};
|
||||
exec = [
|
||||
"waybar"
|
||||
"dunst"
|
||||
];
|
||||
};
|
||||
in lib.toHyprlang {} config
|
||||
```
|
||||
|
||||
**Output:**
|
||||
```nix
|
||||
"$mod = SUPER"
|
||||
"monitor:HDMI-A-1 = 1920x1080@60,0x0,1"
|
||||
"exec = waybar"
|
||||
"exec = dunst"
|
||||
```
|
||||
|
||||
:::
|
||||
*/
|
||||
toHyprlang = {
|
||||
topCommandsPrefixes ? ["$"],
|
||||
bottomCommandsPrefixes ? [],
|
||||
}: attrs: let
|
||||
toHyprlang' = attrs: let
|
||||
# Specially configured `toKeyValue` generator with support for duplicate keys
|
||||
# and a legible key-value separator.
|
||||
mkCommands = generators.toKeyValue {
|
||||
mkKeyValue = generators.mkKeyValueDefault {} " = ";
|
||||
listsAsDuplicateKeys = true;
|
||||
indent = ""; # No indent, since we don't have nesting
|
||||
};
|
||||
|
||||
# Flatten the attrset, combining keys in a "path" like `"a:b:c" = "x"`.
|
||||
# Uses `flattenAttrs` with a colon separator.
|
||||
commands = flattenAttrs (p: k: "${p}:${k}") attrs;
|
||||
|
||||
# General filtering function to check if a key starts with any prefix in a given list.
|
||||
filterCommands = list: n:
|
||||
foldl (acc: prefix: acc || hasPrefix prefix n) false list;
|
||||
|
||||
# Partition keys into top commands and the rest
|
||||
result = partition (filterCommands topCommandsPrefixes) (attrNames commands);
|
||||
topCommands = filterAttrs (n: _: builtins.elem n result.right) commands;
|
||||
remainingCommands = removeAttrs commands result.right;
|
||||
|
||||
# Partition remaining commands into bottom commands and regular commands
|
||||
result2 = partition (filterCommands bottomCommandsPrefixes) result.wrong;
|
||||
bottomCommands = filterAttrs (n: _: builtins.elem n result2.right) remainingCommands;
|
||||
regularCommands = removeAttrs remainingCommands result2.right;
|
||||
in
|
||||
# Concatenate strings from mapping `mkCommands` over top, regular, and bottom commands.
|
||||
concatMapStrings mkCommands [
|
||||
topCommands
|
||||
regularCommands
|
||||
bottomCommands
|
||||
];
|
||||
in
|
||||
toHyprlang' attrs;
|
||||
|
||||
/**
|
||||
Flatten a nested attribute set into a flat attribute set, using a custom key separator function.
|
||||
|
||||
This function recursively traverses a nested attribute set and produces a flat attribute set
|
||||
where keys are joined using a user-defined function (`pred`). It allows transforming deeply
|
||||
nested structures into a single-level attribute set while preserving key-value relationships.
|
||||
|
||||
Configuration:
|
||||
|
||||
* `pred` - A function `(string -> string -> string)` defining how keys should be concatenated.
|
||||
|
||||
# Inputs
|
||||
|
||||
Structured function argument:
|
||||
|
||||
: pred (required)
|
||||
: A function that determines how parent and child keys should be combined into a single key.
|
||||
It takes a `prefix` (parent key) and `key` (current key) and returns the joined key.
|
||||
|
||||
Value:
|
||||
|
||||
: The nested attribute set to be flattened.
|
||||
|
||||
# Type
|
||||
|
||||
```
|
||||
flattenAttrs :: (String -> String -> String) -> AttrSet -> AttrSet
|
||||
```
|
||||
|
||||
# Examples
|
||||
:::{.example}
|
||||
|
||||
```nix
|
||||
let
|
||||
nested = {
|
||||
a = "3";
|
||||
b = { c = "4"; d = "5"; };
|
||||
};
|
||||
|
||||
separator = (prefix: key: "${prefix}.${key}"); # Use dot notation
|
||||
in lib.flattenAttrs separator nested
|
||||
```
|
||||
|
||||
**Output:**
|
||||
```nix
|
||||
{
|
||||
"a" = "3";
|
||||
"b.c" = "4";
|
||||
"b.d" = "5";
|
||||
}
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
*/
|
||||
flattenAttrs = pred: attrs: let
|
||||
flattenAttrs' = prefix: attrs:
|
||||
builtins.foldl' (
|
||||
acc: key: let
|
||||
value = attrs.${key};
|
||||
newKey =
|
||||
if prefix == ""
|
||||
then key
|
||||
else pred prefix key;
|
||||
in
|
||||
acc
|
||||
// (
|
||||
if builtins.isAttrs value
|
||||
then flattenAttrs' newKey value
|
||||
else {"${newKey}" = value;}
|
||||
)
|
||||
) {} (builtins.attrNames attrs);
|
||||
in
|
||||
flattenAttrs' "" attrs;
|
||||
in
|
||||
{
|
||||
inherit flattenAttrs toHyprlang;
|
||||
}
|
132
nix/module.nix
132
nix/module.nix
@@ -5,8 +5,72 @@ inputs: {
|
||||
...
|
||||
}: let
|
||||
inherit (pkgs.stdenv.hostPlatform) system;
|
||||
selflib = import ./lib.nix lib;
|
||||
cfg = config.programs.hyprland;
|
||||
|
||||
# basically 1:1 taken from https://github.com/nix-community/home-manager/blob/master/modules/services/window-managers/hyprland.nix
|
||||
toHyprconf = {
|
||||
attrs,
|
||||
indentLevel ? 0,
|
||||
importantPrefixes ? ["$"],
|
||||
}: let
|
||||
inherit
|
||||
(lib)
|
||||
all
|
||||
concatMapStringsSep
|
||||
concatStrings
|
||||
concatStringsSep
|
||||
filterAttrs
|
||||
foldl
|
||||
generators
|
||||
hasPrefix
|
||||
isAttrs
|
||||
isList
|
||||
mapAttrsToList
|
||||
replicate
|
||||
;
|
||||
|
||||
initialIndent = concatStrings (replicate indentLevel " ");
|
||||
|
||||
toHyprconf' = indent: attrs: let
|
||||
sections =
|
||||
filterAttrs (n: v: isAttrs v || (isList v && all isAttrs v)) attrs;
|
||||
|
||||
mkSection = n: attrs:
|
||||
if lib.isList attrs
|
||||
then (concatMapStringsSep "\n" (a: mkSection n a) attrs)
|
||||
else ''
|
||||
${indent}${n} {
|
||||
${toHyprconf' " ${indent}" attrs}${indent}}
|
||||
'';
|
||||
|
||||
mkFields = generators.toKeyValue {
|
||||
listsAsDuplicateKeys = true;
|
||||
inherit indent;
|
||||
};
|
||||
|
||||
allFields =
|
||||
filterAttrs (n: v: !(isAttrs v || (isList v && all isAttrs v)))
|
||||
attrs;
|
||||
|
||||
isImportantField = n: _:
|
||||
foldl (acc: prev:
|
||||
if hasPrefix prev n
|
||||
then true
|
||||
else acc)
|
||||
false
|
||||
importantPrefixes;
|
||||
|
||||
importantFields = filterAttrs isImportantField allFields;
|
||||
|
||||
fields =
|
||||
builtins.removeAttrs allFields
|
||||
(mapAttrsToList (n: _: n) importantFields);
|
||||
in
|
||||
mkFields importantFields
|
||||
+ concatStringsSep "\n" (mapAttrsToList mkSection sections)
|
||||
+ mkFields fields;
|
||||
in
|
||||
toHyprconf' initialIndent attrs;
|
||||
in {
|
||||
options = {
|
||||
programs.hyprland = {
|
||||
@@ -42,9 +106,6 @@ in {
|
||||
should be written as lists. Variables' and colors' names should be
|
||||
quoted. See <https://wiki.hyprland.org> for more examples.
|
||||
|
||||
Special categories (e.g `devices`) should be written as
|
||||
`"devices[device-name]"`.
|
||||
|
||||
::: {.note}
|
||||
Use the [](#programs.hyprland.plugins) option to
|
||||
declare plugins.
|
||||
@@ -90,21 +151,20 @@ in {
|
||||
'';
|
||||
};
|
||||
|
||||
topPrefixes = lib.mkOption {
|
||||
type = with lib.types; listOf str;
|
||||
default = ["$" "bezier"];
|
||||
example = ["$" "bezier" "source"];
|
||||
description = ''
|
||||
List of prefix of attributes to put at the top of the config.
|
||||
'';
|
||||
};
|
||||
sourceFirst =
|
||||
lib.mkEnableOption ''
|
||||
putting source entries at the top of the configuration
|
||||
''
|
||||
// {
|
||||
default = true;
|
||||
};
|
||||
|
||||
bottomPrefixes = lib.mkOption {
|
||||
importantPrefixes = lib.mkOption {
|
||||
type = with lib.types; listOf str;
|
||||
default = [];
|
||||
example = ["source"];
|
||||
default = ["$" "bezier" "name"] ++ lib.optionals cfg.sourceFirst ["source"];
|
||||
example = ["$" "bezier"];
|
||||
description = ''
|
||||
List of prefix of attributes to put at the bottom of the config.
|
||||
List of prefix of attributes to source at the top of the config.
|
||||
'';
|
||||
};
|
||||
};
|
||||
@@ -113,38 +173,38 @@ in {
|
||||
{
|
||||
programs.hyprland = {
|
||||
package = lib.mkDefault inputs.self.packages.${system}.hyprland;
|
||||
portalPackage = lib.mkDefault inputs.self.packages.${system}.xdg-desktop-portal-hyprland;
|
||||
portalPackage = lib.mkDefault (inputs.self.packages.${system}.xdg-desktop-portal-hyprland.override {
|
||||
hyprland = cfg.finalPackage;
|
||||
});
|
||||
};
|
||||
}
|
||||
(lib.mkIf cfg.enable {
|
||||
environment.etc."xdg/hypr/hyprland.conf" = let
|
||||
shouldGenerate = cfg.extraConfig != "" || cfg.settings != {} || cfg.plugins != [];
|
||||
|
||||
pluginsToHyprlang = plugins:
|
||||
selflib.toHyprlang {
|
||||
topCommandsPrefixes = cfg.topPrefixes;
|
||||
bottomCommandsPrefixes = cfg.bottomPrefixes;
|
||||
}
|
||||
{
|
||||
plugin = let
|
||||
mkEntry = entry:
|
||||
if lib.types.package.check entry
|
||||
then "${entry}/lib/lib${entry.pname}.so"
|
||||
else entry;
|
||||
in
|
||||
map mkEntry cfg.plugins;
|
||||
pluginsToHyprconf = plugins:
|
||||
toHyprconf {
|
||||
attrs = {
|
||||
plugin = let
|
||||
mkEntry = entry:
|
||||
if lib.types.package.check entry
|
||||
then "${entry}/lib/lib${entry.pname}.so"
|
||||
else entry;
|
||||
in
|
||||
map mkEntry cfg.plugins;
|
||||
};
|
||||
inherit (cfg) importantPrefixes;
|
||||
};
|
||||
in
|
||||
lib.mkIf shouldGenerate {
|
||||
text =
|
||||
lib.optionalString (cfg.plugins != [])
|
||||
(pluginsToHyprlang cfg.plugins)
|
||||
(pluginsToHyprconf cfg.plugins)
|
||||
+ lib.optionalString (cfg.settings != {})
|
||||
(selflib.toHyprlang {
|
||||
topCommandsPrefixes = cfg.topPrefixes;
|
||||
bottomCommandsPrefixes = cfg.bottomPrefixes;
|
||||
}
|
||||
cfg.settings)
|
||||
(toHyprconf {
|
||||
attrs = cfg.settings;
|
||||
inherit (cfg) importantPrefixes;
|
||||
})
|
||||
+ lib.optionalString (cfg.extraConfig != "") cfg.extraConfig;
|
||||
};
|
||||
})
|
||||
|
@@ -1,13 +1,13 @@
|
||||
wayland_protos = dependency(
|
||||
'wayland-protocols',
|
||||
version: '>=1.41',
|
||||
version: '>=1.32',
|
||||
fallback: 'wayland-protocols',
|
||||
default_options: ['tests=false'],
|
||||
)
|
||||
|
||||
hyprland_protos = dependency(
|
||||
'hyprland-protocols',
|
||||
version: '>=0.6.2',
|
||||
version: '>=0.6',
|
||||
fallback: 'hyprland-protocols',
|
||||
)
|
||||
|
||||
@@ -70,8 +70,6 @@ protocols = [
|
||||
wayland_protocol_dir / 'staging/xdg-dialog/xdg-dialog-v1.xml',
|
||||
wayland_protocol_dir / 'staging/single-pixel-buffer/single-pixel-buffer-v1.xml',
|
||||
wayland_protocol_dir / 'staging/security-context/security-context-v1.xml',
|
||||
wayland_protocol_dir / 'staging/content-type/content-type-v1.xml',
|
||||
wayland_protocol_dir / 'staging/color-management/color-management-v1.xml',
|
||||
]
|
||||
|
||||
wl_protocols = []
|
||||
|
@@ -1,13 +1,4 @@
|
||||
#!/bin/sh
|
||||
|
||||
# if the git directory doesn't exist, don't gather data to avoid overwriting, unless
|
||||
# the version file is missing altogether (otherwise compiling will fail)
|
||||
if [ ! -d ./.git ]; then
|
||||
if [ -f ./src/version.h ]; then
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
cp -fr ./src/version.h.in ./src/version.h
|
||||
|
||||
HASH=${HASH-$(git rev-parse HEAD)}
|
||||
|
@@ -1,4 +1,3 @@
|
||||
#include <ranges>
|
||||
#include <re2/re2.h>
|
||||
|
||||
#include "Compositor.hpp"
|
||||
@@ -13,7 +12,6 @@
|
||||
#include "managers/SeatManager.hpp"
|
||||
#include "managers/VersionKeeperManager.hpp"
|
||||
#include "managers/DonationNagManager.hpp"
|
||||
#include "managers/ANRManager.hpp"
|
||||
#include "managers/eventLoop/EventLoopManager.hpp"
|
||||
#include <algorithm>
|
||||
#include <aquamarine/output/Output.hpp>
|
||||
@@ -23,12 +21,15 @@
|
||||
#include <print>
|
||||
#include <cstring>
|
||||
#include <filesystem>
|
||||
#include <ranges>
|
||||
#include <print>
|
||||
#include <unordered_set>
|
||||
#include "debug/HyprCtl.hpp"
|
||||
#include "debug/CrashReporter.hpp"
|
||||
#ifdef USES_SYSTEMD
|
||||
#include <helpers/SdDaemon.hpp> // for SdNotify
|
||||
#endif
|
||||
#include "helpers/varlist/VarList.hpp"
|
||||
#include "helpers/fs/FsUtils.hpp"
|
||||
#include "protocols/FractionalScale.hpp"
|
||||
#include "protocols/PointerConstraints.hpp"
|
||||
@@ -70,13 +71,9 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/resource.h>
|
||||
#include <malloc.h>
|
||||
#include <unistd.h>
|
||||
|
||||
using namespace Hyprutils::String;
|
||||
using namespace Aquamarine;
|
||||
using enum NContentType::eContentType;
|
||||
using namespace NColorManagement;
|
||||
|
||||
static int handleCritSignal(int signo, void* data) {
|
||||
Debug::log(LOG, "Hyprland received signal {}", signo);
|
||||
@@ -166,22 +163,10 @@ void CCompositor::restoreNofile() {
|
||||
Debug::log(ERR, "Failed restoring NOFILE limits");
|
||||
}
|
||||
|
||||
void CCompositor::setMallocThreshold() {
|
||||
#ifdef M_TRIM_THRESHOLD
|
||||
// The default is 128 pages,
|
||||
// which is very large and can lead to a lot of memory used for no reason
|
||||
// because trimming hasn't happened
|
||||
static const int PAGESIZE = sysconf(_SC_PAGESIZE);
|
||||
mallopt(M_TRIM_THRESHOLD, 6 * PAGESIZE);
|
||||
#endif
|
||||
}
|
||||
|
||||
CCompositor::CCompositor(bool onlyConfig) : m_bOnlyConfigVerification(onlyConfig), m_iHyprlandPID(getpid()) {
|
||||
if (onlyConfig)
|
||||
return;
|
||||
|
||||
setMallocThreshold();
|
||||
|
||||
m_szHyprTempDataRoot = std::string{getenv("XDG_RUNTIME_DIR")} + "/hypr";
|
||||
|
||||
if (m_szHyprTempDataRoot.starts_with("/hypr")) {
|
||||
@@ -280,6 +265,7 @@ static bool filterGlobals(const wl_client* client, const wl_global* global, void
|
||||
|
||||
//
|
||||
void CCompositor::initServer(std::string socketName, int socketFd) {
|
||||
|
||||
if (m_bOnlyConfigVerification) {
|
||||
g_pHookSystem = makeUnique<CHookSystemManager>();
|
||||
g_pKeybindManager = makeUnique<CKeybindManager>();
|
||||
@@ -388,6 +374,7 @@ void CCompositor::initServer(std::string socketName, int socketFd) {
|
||||
}
|
||||
|
||||
setenv("WAYLAND_DISPLAY", m_szWLDisplaySocket.c_str(), 1);
|
||||
setenv("XDG_SESSION_TYPE", "wayland", 1);
|
||||
if (!getenv("XDG_CURRENT_DESKTOP")) {
|
||||
setenv("XDG_CURRENT_DESKTOP", "Hyprland", 1);
|
||||
m_bDesktopEnvSet = true;
|
||||
@@ -514,7 +501,7 @@ void CCompositor::cleanEnvironment() {
|
||||
"dbus-update-activation-environment 2>/dev/null && "
|
||||
#endif
|
||||
"dbus-update-activation-environment --systemd WAYLAND_DISPLAY XDG_CURRENT_DESKTOP HYPRLAND_INSTANCE_SIGNATURE QT_QPA_PLATFORMTHEME PATH XDG_DATA_DIRS";
|
||||
CKeybindManager::spawn(CMD);
|
||||
g_pKeybindManager->spawn(CMD);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -594,7 +581,6 @@ void CCompositor::cleanup() {
|
||||
g_pEventLoopManager.reset();
|
||||
g_pVersionKeeperMgr.reset();
|
||||
g_pDonationNagManager.reset();
|
||||
g_pANRManager.reset();
|
||||
g_pConfigWatcher.reset();
|
||||
|
||||
if (m_pAqBackend)
|
||||
@@ -697,9 +683,6 @@ void CCompositor::initManagers(eManagersInitStage stage) {
|
||||
Debug::log(LOG, "Creating the DonationNag!");
|
||||
g_pDonationNagManager = makeUnique<CDonationNagManager>();
|
||||
|
||||
Debug::log(LOG, "Creating the ANRManager!");
|
||||
g_pANRManager = makeUnique<CANRManager>();
|
||||
|
||||
Debug::log(LOG, "Starting XWayland");
|
||||
g_pXWayland = makeUnique<CXWayland>(g_pCompositor->m_bWantsXwayland);
|
||||
} break;
|
||||
@@ -756,7 +739,7 @@ void CCompositor::startCompositor() {
|
||||
"dbus-update-activation-environment 2>/dev/null && "
|
||||
#endif
|
||||
"dbus-update-activation-environment --systemd WAYLAND_DISPLAY XDG_CURRENT_DESKTOP HYPRLAND_INSTANCE_SIGNATURE QT_QPA_PLATFORMTHEME PATH XDG_DATA_DIRS";
|
||||
CKeybindManager::spawn(CMD);
|
||||
g_pKeybindManager->spawn(CMD);
|
||||
}
|
||||
|
||||
Debug::log(LOG, "Running on WAYLAND_DISPLAY: {}", m_szWLDisplaySocket);
|
||||
@@ -815,11 +798,6 @@ PHLMONITOR CCompositor::getMonitorFromCursor() {
|
||||
}
|
||||
|
||||
PHLMONITOR CCompositor::getMonitorFromVector(const Vector2D& point) {
|
||||
if (m_vMonitors.empty()) {
|
||||
Debug::log(WARN, "getMonitorFromVector called with empty monitor list");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
PHLMONITOR mon;
|
||||
for (auto const& m : m_vMonitors) {
|
||||
if (CBox{m->vecPosition, m->vecSize}.containsPoint(point)) {
|
||||
@@ -862,7 +840,12 @@ void CCompositor::removeWindowFromVectorSafe(PHLWINDOW pWindow) {
|
||||
}
|
||||
|
||||
bool CCompositor::monitorExists(PHLMONITOR pMonitor) {
|
||||
return std::ranges::any_of(m_vRealMonitors, [&](const PHLMONITOR& m) { return m == pMonitor; });
|
||||
for (auto const& m : m_vRealMonitors) {
|
||||
if (m == pMonitor)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
PHLWINDOW CCompositor::vectorToWindowUnified(const Vector2D& pos, uint8_t properties, PHLWINDOW pIgnoreWindow) {
|
||||
@@ -1082,7 +1065,7 @@ PHLMONITOR CCompositor::getRealMonitorFromOutput(SP<Aquamarine::IOutput> out) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void CCompositor::focusWindow(PHLWINDOW pWindow, SP<CWLSurfaceResource> pSurface, bool preserveFocusHistory) {
|
||||
void CCompositor::focusWindow(PHLWINDOW pWindow, SP<CWLSurfaceResource> pSurface) {
|
||||
|
||||
static auto PFOLLOWMOUSE = CConfigValue<Hyprlang::INT>("input:follow_mouse");
|
||||
static auto PSPECIALFALLTHROUGH = CConfigValue<Hyprlang::INT>("input:special_fallthrough");
|
||||
@@ -1193,8 +1176,8 @@ void CCompositor::focusWindow(PHLWINDOW pWindow, SP<CWLSurfaceResource> pSurface
|
||||
pWindow->m_bIsUrgent = false;
|
||||
|
||||
// Send an event
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{.event = "activewindow", .data = pWindow->m_szClass + "," + pWindow->m_szTitle});
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{.event = "activewindowv2", .data = std::format("{:x}", (uintptr_t)pWindow.get())});
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"activewindow", pWindow->m_szClass + "," + pWindow->m_szTitle});
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"activewindowv2", std::format("{:x}", (uintptr_t)pWindow.get())});
|
||||
|
||||
EMIT_HOOK_EVENT("activeWindow", pWindow);
|
||||
|
||||
@@ -1202,20 +1185,16 @@ void CCompositor::focusWindow(PHLWINDOW pWindow, SP<CWLSurfaceResource> pSurface
|
||||
|
||||
g_pInputManager->recheckIdleInhibitorStatus();
|
||||
|
||||
if (!preserveFocusHistory) {
|
||||
// move to front of the window history
|
||||
const auto HISTORYPIVOT = std::ranges::find_if(m_vWindowFocusHistory, [&](const auto& other) { return other.lock() == pWindow; });
|
||||
if (HISTORYPIVOT == m_vWindowFocusHistory.end())
|
||||
Debug::log(ERR, "BUG THIS: {} has no pivot in history", pWindow);
|
||||
else
|
||||
std::rotate(m_vWindowFocusHistory.begin(), HISTORYPIVOT, HISTORYPIVOT + 1);
|
||||
// move to front of the window history
|
||||
const auto HISTORYPIVOT = std::find_if(m_vWindowFocusHistory.begin(), m_vWindowFocusHistory.end(), [&](const auto& other) { return other.lock() == pWindow; });
|
||||
if (HISTORYPIVOT == m_vWindowFocusHistory.end()) {
|
||||
Debug::log(ERR, "BUG THIS: {} has no pivot in history", pWindow);
|
||||
} else {
|
||||
std::rotate(m_vWindowFocusHistory.begin(), HISTORYPIVOT, HISTORYPIVOT + 1);
|
||||
}
|
||||
|
||||
if (*PFOLLOWMOUSE == 0)
|
||||
g_pInputManager->sendMotionEventsToFocused();
|
||||
|
||||
if (pWindow->m_sGroupData.pNextWindow)
|
||||
pWindow->deactivateGroupMembers();
|
||||
}
|
||||
|
||||
void CCompositor::focusSurface(SP<CWLSurfaceResource> pSurface, PHLWINDOW pWindowOwner) {
|
||||
@@ -1239,8 +1218,8 @@ void CCompositor::focusSurface(SP<CWLSurfaceResource> pSurface, PHLWINDOW pWindo
|
||||
|
||||
if (!pSurface) {
|
||||
g_pSeatManager->setKeyboardFocus(nullptr);
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{.event = "activewindow", .data = ","});
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{.event = "activewindowv2", .data = ""});
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"activewindow", ","}); // unfocused
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"activewindowv2", ""});
|
||||
EMIT_HOOK_EVENT("keyboardFocus", (SP<CWLSurfaceResource>)nullptr);
|
||||
m_pLastFocus.reset();
|
||||
return;
|
||||
@@ -1272,7 +1251,7 @@ void CCompositor::focusSurface(SP<CWLSurfaceResource> pSurface, PHLWINDOW pWindo
|
||||
SP<CWLSurfaceResource> CCompositor::vectorToLayerPopupSurface(const Vector2D& pos, PHLMONITOR monitor, Vector2D* sCoords, PHLLS* ppLayerSurfaceFound) {
|
||||
for (auto const& lsl : monitor->m_aLayerSurfaceLayers | std::views::reverse) {
|
||||
for (auto const& ls : lsl | std::views::reverse) {
|
||||
if (!ls->mapped || ls->fadingOut || !ls->layerSurface || (ls->layerSurface && !ls->layerSurface->mapped) || ls->alpha->value() == 0.f)
|
||||
if (ls->fadingOut || !ls->layerSurface || (ls->layerSurface && !ls->layerSurface->mapped) || ls->alpha->value() == 0.f)
|
||||
continue;
|
||||
|
||||
auto SURFACEAT = ls->popupHead->at(pos, true);
|
||||
@@ -1290,7 +1269,7 @@ SP<CWLSurfaceResource> CCompositor::vectorToLayerPopupSurface(const Vector2D& po
|
||||
|
||||
SP<CWLSurfaceResource> CCompositor::vectorToLayerSurface(const Vector2D& pos, std::vector<PHLLSREF>* layerSurfaces, Vector2D* sCoords, PHLLS* ppLayerSurfaceFound) {
|
||||
for (auto const& ls : *layerSurfaces | std::views::reverse) {
|
||||
if (!ls->mapped || ls->fadingOut || !ls->layerSurface || (ls->layerSurface && !ls->layerSurface->surface->mapped) || ls->alpha->value() == 0.f)
|
||||
if (ls->fadingOut || !ls->layerSurface || (ls->layerSurface && !ls->layerSurface->surface->mapped) || ls->alpha->value() == 0.f)
|
||||
continue;
|
||||
|
||||
auto [surf, local] = ls->layerSurface->surface->at(pos - ls->geometry.pos(), true);
|
||||
@@ -1417,13 +1396,14 @@ void CCompositor::changeWindowZOrder(PHLWINDOW pWindow, bool top) {
|
||||
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::ranges::find(toMove, 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);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
x11Stack(pWindow, top, x11Stack);
|
||||
|
||||
for (const auto& it : toMove) {
|
||||
moveToZ(it, top);
|
||||
}
|
||||
@@ -1475,7 +1455,7 @@ void CCompositor::cleanupFadingOut(const MONITORID& monid) {
|
||||
if (ls->fadingOut && ls->readyToDelete && ls->isFadedOut()) {
|
||||
for (auto const& m : m_vMonitors) {
|
||||
for (auto& lsl : m->m_aLayerSurfaceLayers) {
|
||||
if (!lsl.empty() && std::ranges::find_if(lsl, [&](auto& other) { return other == ls; }) != lsl.end()) {
|
||||
if (!lsl.empty() && std::find_if(lsl.begin(), lsl.end(), [&](auto& other) { return other == ls; }) != lsl.end()) {
|
||||
std::erase_if(lsl, [&](auto& other) { return other == ls || !other; });
|
||||
}
|
||||
}
|
||||
@@ -1498,7 +1478,7 @@ void CCompositor::cleanupFadingOut(const MONITORID& monid) {
|
||||
}
|
||||
|
||||
void CCompositor::addToFadingOutSafe(PHLLS pLS) {
|
||||
const auto FOUND = std::ranges::find_if(m_vSurfacesFadingOut, [&](auto& other) { return other.lock() == pLS; });
|
||||
const auto FOUND = std::find_if(m_vSurfacesFadingOut.begin(), m_vSurfacesFadingOut.end(), [&](auto& other) { return other.lock() == pLS; });
|
||||
|
||||
if (FOUND != m_vSurfacesFadingOut.end())
|
||||
return; // if it's already added, don't add it.
|
||||
@@ -1511,7 +1491,7 @@ void CCompositor::removeFromFadingOutSafe(PHLLS ls) {
|
||||
}
|
||||
|
||||
void CCompositor::addToFadingOutSafe(PHLWINDOW pWindow) {
|
||||
const auto FOUND = std::ranges::find_if(m_vWindowsFadingOut, [&](PHLWINDOWREF& other) { return other.lock() == pWindow; });
|
||||
const auto FOUND = std::find_if(m_vWindowsFadingOut.begin(), m_vWindowsFadingOut.end(), [&](PHLWINDOWREF& other) { return other.lock() == pWindow; });
|
||||
|
||||
if (FOUND != m_vWindowsFadingOut.end())
|
||||
return; // if it's already added, don't add it.
|
||||
@@ -1630,7 +1610,7 @@ PHLWINDOW CCompositor::getWindowInDirection(const CBox& box, PHLWORKSPACE pWorks
|
||||
|
||||
//
|
||||
auto vectorAngles = [](const Vector2D& a, const Vector2D& b) -> double {
|
||||
double dot = (a.x * b.x) + (a.y * b.y);
|
||||
double dot = a.x * b.x + a.y * b.y;
|
||||
double ang = std::acos(dot / (a.size() * b.size()));
|
||||
return ang;
|
||||
};
|
||||
@@ -1674,52 +1654,37 @@ PHLWINDOW CCompositor::getWindowInDirection(const CBox& box, PHLWORKSPACE pWorks
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template <typename WINDOWPTR>
|
||||
static bool isWorkspaceMatches(WINDOWPTR pWindow, const WINDOWPTR w, bool anyWorkspace) {
|
||||
PHLWINDOW CCompositor::getNextWindowOnWorkspace(PHLWINDOW pWindow, bool focusableOnly, std::optional<bool> floating, bool visible) {
|
||||
auto it = std::ranges::find(m_vWindows, pWindow);
|
||||
const auto FINDER = [&](const PHLWINDOW& w) { return isWindowAvailableForCycle(pWindow, w, focusableOnly, floating, visible); };
|
||||
const auto IN_RIGHT = std::find_if(it, m_vWindows.end(), FINDER);
|
||||
if (IN_RIGHT != m_vWindows.end())
|
||||
return *IN_RIGHT;
|
||||
const auto IN_LEFT = std::find_if(m_vWindows.begin(), it, FINDER);
|
||||
return *IN_LEFT;
|
||||
}
|
||||
|
||||
PHLWINDOW CCompositor::getPrevWindowOnWorkspace(PHLWINDOW pWindow, bool focusableOnly, std::optional<bool> floating, bool visible) {
|
||||
auto it = std::ranges::find(std::ranges::reverse_view(m_vWindows), pWindow);
|
||||
const auto FINDER = [&](const PHLWINDOW& w) { return isWindowAvailableForCycle(pWindow, w, focusableOnly, floating, visible); };
|
||||
const auto IN_LEFT = std::find_if(it, m_vWindows.rend(), FINDER);
|
||||
if (IN_LEFT != m_vWindows.rend())
|
||||
return *IN_LEFT;
|
||||
const auto IN_RIGHT = std::find_if(m_vWindows.rbegin(), it, FINDER);
|
||||
return *IN_RIGHT;
|
||||
}
|
||||
|
||||
inline static bool isWorkspaceMatches(PHLWINDOW pWindow, const PHLWINDOW w, bool anyWorkspace) {
|
||||
return anyWorkspace ? w->m_pWorkspace && w->m_pWorkspace->isVisible() : w->m_pWorkspace == pWindow->m_pWorkspace;
|
||||
}
|
||||
|
||||
template <typename WINDOWPTR>
|
||||
static bool isFloatingMatches(WINDOWPTR w, std::optional<bool> floating) {
|
||||
inline static bool isFloatingMatches(PHLWINDOW w, std::optional<bool> floating) {
|
||||
return !floating.has_value() || w->m_bIsFloating == floating.value();
|
||||
}
|
||||
};
|
||||
|
||||
template <typename WINDOWPTR>
|
||||
static bool isWindowAvailableForCycle(WINDOWPTR pWindow, WINDOWPTR w, bool focusableOnly, std::optional<bool> floating, bool anyWorkspace = false) {
|
||||
return isFloatingMatches(w, floating) &&
|
||||
(w != pWindow && isWorkspaceMatches(pWindow, w, anyWorkspace) && w->m_bIsMapped && !w->isHidden() && (!focusableOnly || !w->m_sWindowData.noFocus.valueOrDefault()));
|
||||
}
|
||||
|
||||
template <typename Iterator>
|
||||
static PHLWINDOW getWindowPred(Iterator cur, Iterator end, Iterator begin, const std::function<bool(const PHLWINDOW&)> PRED) {
|
||||
const auto IN_ONE_SIDE = std::find_if(cur, end, PRED);
|
||||
if (IN_ONE_SIDE != end)
|
||||
return *IN_ONE_SIDE;
|
||||
const auto IN_OTHER_SIDE = std::find_if(begin, cur, PRED);
|
||||
return *IN_OTHER_SIDE;
|
||||
}
|
||||
|
||||
template <typename Iterator>
|
||||
static PHLWINDOW getWeakWindowPred(Iterator cur, Iterator end, Iterator begin, const std::function<bool(const PHLWINDOWREF&)> PRED) {
|
||||
const auto IN_ONE_SIDE = std::find_if(cur, end, PRED);
|
||||
if (IN_ONE_SIDE != end)
|
||||
return IN_ONE_SIDE->lock();
|
||||
const auto IN_OTHER_SIDE = std::find_if(begin, cur, PRED);
|
||||
return IN_OTHER_SIDE->lock();
|
||||
}
|
||||
|
||||
PHLWINDOW CCompositor::getWindowCycleHist(PHLWINDOWREF cur, bool focusableOnly, std::optional<bool> floating, bool visible, bool next) {
|
||||
const auto FINDER = [&](const PHLWINDOWREF& w) { return isWindowAvailableForCycle(cur, w, focusableOnly, floating, visible); };
|
||||
// also m_vWindowFocusHistory has reverse order, so when it is next - we need to reverse again
|
||||
return next ?
|
||||
getWeakWindowPred(std::ranges::find(std::ranges::reverse_view(m_vWindowFocusHistory), cur), m_vWindowFocusHistory.rend(), m_vWindowFocusHistory.rbegin(), FINDER) :
|
||||
getWeakWindowPred(std::ranges::find(m_vWindowFocusHistory, cur), m_vWindowFocusHistory.end(), m_vWindowFocusHistory.begin(), FINDER);
|
||||
}
|
||||
|
||||
PHLWINDOW CCompositor::getWindowCycle(PHLWINDOW cur, bool focusableOnly, std::optional<bool> floating, bool visible, bool prev) {
|
||||
const auto FINDER = [&](const PHLWINDOW& w) { return isWindowAvailableForCycle(cur, w, focusableOnly, floating, visible); };
|
||||
return prev ? getWindowPred(std::ranges::find(std::ranges::reverse_view(m_vWindows), cur), m_vWindows.rend(), m_vWindows.rbegin(), FINDER) :
|
||||
getWindowPred(std::ranges::find(m_vWindows, cur), m_vWindows.end(), m_vWindows.begin(), FINDER);
|
||||
bool CCompositor::isWindowAvailableForCycle(PHLWINDOW pWindow, const PHLWINDOW w, bool focusableOnly, std::optional<bool> floating, bool anyWorkspace) {
|
||||
return isFloatingMatches(w, floating) && w != pWindow && isWorkspaceMatches(pWindow, w, anyWorkspace) && w->m_bIsMapped && !w->isHidden() &&
|
||||
(!focusableOnly || !w->m_sWindowData.noFocus.valueOrDefault());
|
||||
}
|
||||
|
||||
WORKSPACEID CCompositor::getNextAvailableNamedWorkspace() {
|
||||
@@ -1764,7 +1729,7 @@ bool CCompositor::isPointOnReservedArea(const Vector2D& point, const PHLMONITOR
|
||||
const auto XY1 = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft;
|
||||
const auto XY2 = PMONITOR->vecPosition + PMONITOR->vecSize - PMONITOR->vecReservedBottomRight;
|
||||
|
||||
return VECNOTINRECT(point, XY1.x, XY1.y, XY2.x, XY2.y);
|
||||
return !VECINRECT(point, XY1.x, XY1.y, XY2.x, XY2.y);
|
||||
}
|
||||
|
||||
PHLMONITOR CCompositor::getMonitorInDirection(const char& dir) {
|
||||
@@ -1938,7 +1903,7 @@ void CCompositor::updateWindowAnimatedDecorationValues(PHLWINDOW pWindow) {
|
||||
|
||||
MONITORID CCompositor::getNextAvailableMonitorID(std::string const& name) {
|
||||
// reuse ID if it's already in the map, and the monitor with that ID is not being used by another monitor
|
||||
if (m_mMonitorIDMap.contains(name) && !std::ranges::any_of(m_vRealMonitors, [&](auto m) { return m->ID == m_mMonitorIDMap[name]; }))
|
||||
if (m_mMonitorIDMap.contains(name) && !std::any_of(m_vRealMonitors.begin(), m_vRealMonitors.end(), [&](auto m) { return m->ID == m_mMonitorIDMap[name]; }))
|
||||
return m_mMonitorIDMap[name];
|
||||
|
||||
// otherwise, find minimum available ID that is not in the map
|
||||
@@ -1948,7 +1913,7 @@ MONITORID CCompositor::getNextAvailableMonitorID(std::string const& name) {
|
||||
}
|
||||
|
||||
MONITORID nextID = 0;
|
||||
while (usedIDs.contains(nextID)) {
|
||||
while (usedIDs.count(nextID) > 0) {
|
||||
nextID++;
|
||||
}
|
||||
m_mMonitorIDMap[name] = nextID;
|
||||
@@ -1956,6 +1921,7 @@ MONITORID CCompositor::getNextAvailableMonitorID(std::string const& name) {
|
||||
}
|
||||
|
||||
void CCompositor::swapActiveWorkspaces(PHLMONITOR pMonitorA, PHLMONITOR pMonitorB) {
|
||||
|
||||
const auto PWORKSPACEA = pMonitorA->activeWorkspace;
|
||||
const auto PWORKSPACEB = pMonitorB->activeWorkspace;
|
||||
|
||||
@@ -2027,18 +1993,17 @@ void CCompositor::swapActiveWorkspaces(PHLMONITOR pMonitorA, PHLMONITOR pMonitor
|
||||
(g_pCompositor->vectorToWindowUnified(g_pInputManager->getMouseCoordsInternal(), RESERVED_EXTENTS | INPUT_EXTENTS | ALLOW_FLOATING)));
|
||||
|
||||
const auto PNEWWORKSPACE = pMonitorA->ID == g_pCompositor->m_pLastMonitor->ID ? PWORKSPACEB : PWORKSPACEA;
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{.event = "workspace", .data = PNEWWORKSPACE->m_szName});
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{.event = "workspacev2", .data = std::format("{},{}", PNEWWORKSPACE->m_iID, PNEWWORKSPACE->m_szName)});
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"workspace", PNEWWORKSPACE->m_szName});
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"workspacev2", std::format("{},{}", PNEWWORKSPACE->m_iID, PNEWWORKSPACE->m_szName)});
|
||||
EMIT_HOOK_EVENT("workspace", PNEWWORKSPACE);
|
||||
}
|
||||
|
||||
// event
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{.event = "moveworkspace", .data = PWORKSPACEA->m_szName + "," + pMonitorB->szName});
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{.event = "moveworkspacev2", .data = std::format("{},{},{}", PWORKSPACEA->m_iID, PWORKSPACEA->m_szName, pMonitorB->szName)});
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"moveworkspace", PWORKSPACEA->m_szName + "," + pMonitorB->szName});
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"moveworkspacev2", std::format("{},{},{}", PWORKSPACEA->m_iID, PWORKSPACEA->m_szName, pMonitorB->szName)});
|
||||
EMIT_HOOK_EVENT("moveWorkspace", (std::vector<std::any>{PWORKSPACEA, pMonitorB}));
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{.event = "moveworkspace", .data = PWORKSPACEB->m_szName + "," + pMonitorA->szName});
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{.event = "moveworkspacev2", .data = std::format("{},{},{}", PWORKSPACEB->m_iID, PWORKSPACEB->m_szName, pMonitorA->szName)});
|
||||
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"moveworkspace", PWORKSPACEB->m_szName + "," + pMonitorA->szName});
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"moveworkspacev2", std::format("{},{},{}", PWORKSPACEB->m_iID, PWORKSPACEB->m_szName, pMonitorA->szName)});
|
||||
EMIT_HOOK_EVENT("moveWorkspace", (std::vector<std::any>{PWORKSPACEB, pMonitorA}));
|
||||
}
|
||||
|
||||
@@ -2117,6 +2082,7 @@ PHLMONITOR CCompositor::getMonitorFromString(const std::string& name) {
|
||||
}
|
||||
|
||||
void CCompositor::moveWorkspaceToMonitor(PHLWORKSPACE pWorkspace, PHLMONITOR pMonitor, bool noWarpCursor) {
|
||||
|
||||
if (!pWorkspace || !pMonitor)
|
||||
return;
|
||||
|
||||
@@ -2215,8 +2181,7 @@ void CCompositor::moveWorkspaceToMonitor(PHLWORKSPACE pWorkspace, PHLMONITOR pMo
|
||||
// finalize
|
||||
if (POLDMON) {
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(POLDMON->ID);
|
||||
if (valid(POLDMON->activeWorkspace))
|
||||
updateFullscreenFadeOnWorkspace(POLDMON->activeWorkspace);
|
||||
updateFullscreenFadeOnWorkspace(POLDMON->activeWorkspace);
|
||||
updateSuspendedStates();
|
||||
}
|
||||
|
||||
@@ -2224,8 +2189,8 @@ void CCompositor::moveWorkspaceToMonitor(PHLWORKSPACE pWorkspace, PHLMONITOR pMo
|
||||
updateSuspendedStates();
|
||||
|
||||
// event
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{.event = "moveworkspace", .data = pWorkspace->m_szName + "," + pMonitor->szName});
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{.event = "moveworkspacev2", .data = std::format("{},{},{}", pWorkspace->m_iID, pWorkspace->m_szName, pMonitor->szName)});
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"moveworkspace", pWorkspace->m_szName + "," + pMonitor->szName});
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"moveworkspacev2", std::format("{},{},{}", pWorkspace->m_iID, pWorkspace->m_szName, pMonitor->szName)});
|
||||
EMIT_HOOK_EVENT("moveWorkspace", (std::vector<std::any>{pWorkspace, pMonitor}));
|
||||
}
|
||||
|
||||
@@ -2236,8 +2201,12 @@ bool CCompositor::workspaceIDOutOfBounds(const WORKSPACEID& id) {
|
||||
for (auto const& w : m_vWorkspaces) {
|
||||
if (w->m_bIsSpecialWorkspace)
|
||||
continue;
|
||||
lowestID = std::min(w->m_iID, lowestID);
|
||||
highestID = std::max(w->m_iID, highestID);
|
||||
|
||||
if (w->m_iID < lowestID)
|
||||
lowestID = w->m_iID;
|
||||
|
||||
if (w->m_iID > highestID)
|
||||
highestID = w->m_iID;
|
||||
}
|
||||
|
||||
return std::clamp(id, lowestID, highestID) != id;
|
||||
@@ -2245,9 +2214,6 @@ bool CCompositor::workspaceIDOutOfBounds(const WORKSPACEID& id) {
|
||||
|
||||
void CCompositor::updateFullscreenFadeOnWorkspace(PHLWORKSPACE pWorkspace) {
|
||||
|
||||
if (!pWorkspace)
|
||||
return;
|
||||
|
||||
const auto FULLSCREEN = pWorkspace->m_bHasFullscreenWindow;
|
||||
|
||||
for (auto const& w : g_pCompositor->m_vWindows) {
|
||||
@@ -2316,7 +2282,7 @@ void CCompositor::setWindowFullscreenState(const PHLWINDOW PWINDOW, SFullscreenS
|
||||
if (PWORKSPACE->m_bHasFullscreenWindow && !PWINDOW->isFullscreen())
|
||||
setWindowFullscreenInternal(PWORKSPACE->getFullscreenWindow(), FSMODE_NONE);
|
||||
|
||||
const bool CHANGEINTERNAL = !PWINDOW->m_bPinned && CURRENT_EFFECTIVE_MODE != EFFECTIVE_MODE;
|
||||
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;
|
||||
@@ -2343,7 +2309,7 @@ void CCompositor::setWindowFullscreenState(const PHLWINDOW PWINDOW, SFullscreenS
|
||||
PWORKSPACE->m_efFullscreenMode = EFFECTIVE_MODE;
|
||||
PWORKSPACE->m_bHasFullscreenWindow = EFFECTIVE_MODE != FSMODE_NONE;
|
||||
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{.event = "fullscreen", .data = std::to_string((int)EFFECTIVE_MODE != FSMODE_NONE)});
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"fullscreen", std::to_string((int)EFFECTIVE_MODE != FSMODE_NONE)});
|
||||
EMIT_HOOK_EVENT("fullscreen", PWINDOW);
|
||||
|
||||
PWINDOW->updateDynamicRules();
|
||||
@@ -2358,7 +2324,7 @@ void CCompositor::setWindowFullscreenState(const PHLWINDOW PWINDOW, SFullscreenS
|
||||
|
||||
updateFullscreenFadeOnWorkspace(PWORKSPACE);
|
||||
|
||||
PWINDOW->sendWindowSize(true);
|
||||
PWINDOW->sendWindowSize(PWINDOW->m_vRealSize->goal(), true);
|
||||
|
||||
PWORKSPACE->forceReportSizesToWindows();
|
||||
|
||||
@@ -2370,7 +2336,7 @@ void CCompositor::setWindowFullscreenState(const PHLWINDOW PWINDOW, SFullscreenS
|
||||
|
||||
// send a scanout tranche if we are entering fullscreen, and send a regular one if we aren't.
|
||||
// ignore if DS is disabled.
|
||||
if (*PDIRECTSCANOUT == 1 || (*PDIRECTSCANOUT == 2 && PWINDOW->getContentType() == CONTENT_TYPE_GAME))
|
||||
if (*PDIRECTSCANOUT)
|
||||
g_pHyprRenderer->setSurfaceScanoutMode(PWINDOW->m_pWLSurface->resource(), EFFECTIVE_MODE != FSMODE_NONE ? PMONITOR->self.lock() : nullptr);
|
||||
|
||||
g_pConfigManager->ensureVRR(PMONITOR);
|
||||
@@ -2610,8 +2576,8 @@ Vector2D CCompositor::parseWindowVectorArgsRelative(const std::string& args, con
|
||||
X = xIsPercent ? std::stof(x) * 0.01 * PMONITOR->vecSize.x : std::stoi(x);
|
||||
Y = yIsPercent ? std::stof(y) * 0.01 * PMONITOR->vecSize.y : std::stoi(y);
|
||||
} else {
|
||||
X = xIsPercent ? (std::stof(x) * 0.01 * relativeTo.x) + relativeTo.x : std::stoi(x) + relativeTo.x;
|
||||
Y = yIsPercent ? (std::stof(y) * 0.01 * relativeTo.y) + relativeTo.y : std::stoi(y) + relativeTo.y;
|
||||
X = xIsPercent ? std::stof(x) * 0.01 * relativeTo.x + relativeTo.x : std::stoi(x) + relativeTo.x;
|
||||
Y = yIsPercent ? std::stof(y) * 0.01 * relativeTo.y + relativeTo.y : std::stoi(y) + relativeTo.y;
|
||||
}
|
||||
|
||||
return Vector2D(X, Y);
|
||||
@@ -2627,13 +2593,7 @@ PHLWORKSPACE CCompositor::createNewWorkspace(const WORKSPACEID& id, const MONITO
|
||||
|
||||
const bool SPECIAL = id >= SPECIAL_WORKSPACE_START && id <= -2;
|
||||
|
||||
const auto PMONITOR = getMonitorFromID(monID);
|
||||
if (!PMONITOR) {
|
||||
Debug::log(ERR, "BUG THIS: No pMonitor for new workspace in createNewWorkspace");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const auto PWORKSPACE = m_vWorkspaces.emplace_back(CWorkspace::create(id, PMONITOR, NAME, SPECIAL, isEmpty));
|
||||
const auto PWORKSPACE = m_vWorkspaces.emplace_back(CWorkspace::create(id, getMonitorFromID(monID), NAME, SPECIAL, isEmpty));
|
||||
|
||||
PWORKSPACE->m_fAlpha->setValueAndWarp(0);
|
||||
|
||||
@@ -2654,8 +2614,8 @@ void CCompositor::setActiveMonitor(PHLMONITOR pMonitor) {
|
||||
const auto WORKSPACE_ID = PWORKSPACE ? std::to_string(PWORKSPACE->m_iID) : std::to_string(WORKSPACE_INVALID);
|
||||
const auto WORKSPACE_NAME = PWORKSPACE ? PWORKSPACE->m_szName : "?";
|
||||
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{.event = "focusedmon", .data = pMonitor->szName + "," + WORKSPACE_NAME});
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{.event = "focusedmonv2", .data = pMonitor->szName + "," + WORKSPACE_ID});
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"focusedmon", pMonitor->szName + "," + WORKSPACE_NAME});
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"focusedmonv2", pMonitor->szName + "," + WORKSPACE_ID});
|
||||
|
||||
EMIT_HOOK_EVENT("focusedMon", pMonitor);
|
||||
m_pLastMonitor = pMonitor->self;
|
||||
@@ -2711,9 +2671,6 @@ void CCompositor::moveWindowToWorkspaceSafe(PHLWINDOW pWindow, PHLWORKSPACE pWor
|
||||
if (pWindow->m_bPinned && pWorkspace->m_bIsSpecialWorkspace)
|
||||
return;
|
||||
|
||||
if (pWindow->m_pWorkspace == pWorkspace)
|
||||
return;
|
||||
|
||||
const bool FULLSCREEN = pWindow->isFullscreen();
|
||||
const auto FULLSCREENMODE = pWindow->m_sFullscreenState.internal;
|
||||
const bool WASVISIBLE = pWindow->m_pWorkspace && pWindow->m_pWorkspace->isVisible();
|
||||
@@ -2848,10 +2805,14 @@ void CCompositor::arrangeMonitors() {
|
||||
|
||||
// Finds the max and min values of explicitely placed monitors.
|
||||
for (auto const& m : arranged) {
|
||||
maxXOffsetRight = std::max<double>(m->vecPosition.x + m->vecSize.x, maxXOffsetRight);
|
||||
maxXOffsetLeft = std::min<double>(m->vecPosition.x, maxXOffsetLeft);
|
||||
maxYOffsetDown = std::max<double>(m->vecPosition.y + m->vecSize.y, maxYOffsetDown);
|
||||
maxYOffsetUp = std::min<double>(m->vecPosition.y, maxYOffsetUp);
|
||||
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;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -3045,10 +3006,8 @@ void CCompositor::onNewMonitor(SP<Aquamarine::IOutput> output) {
|
||||
g_pHyprRenderer->damageMonitor(PNEWMONITOR);
|
||||
PNEWMONITOR->onMonitorFrame();
|
||||
|
||||
if (PROTO::colorManagement && shouldChangePreferredImageDescription()) {
|
||||
Debug::log(ERR, "FIXME: color management protocol is enabled, need a preferred image description id");
|
||||
PROTO::colorManagement->onImagePreferredChanged(0);
|
||||
}
|
||||
if (PROTO::colorManagement && shouldChangePreferredImageDescription())
|
||||
PROTO::colorManagement->onImagePreferredChanged();
|
||||
}
|
||||
|
||||
SImageDescription CCompositor::getPreferredImageDescription() {
|
||||
@@ -3066,58 +3025,34 @@ bool CCompositor::shouldChangePreferredImageDescription() {
|
||||
return false;
|
||||
}
|
||||
|
||||
void CCompositor::ensurePersistentWorkspacesPresent(const std::vector<SWorkspaceRule>& rules, PHLWORKSPACE pWorkspace) {
|
||||
if (!m_pLastMonitor)
|
||||
return;
|
||||
|
||||
void CCompositor::ensurePersistentWorkspacesPresent(const std::vector<SWorkspaceRule>& rules) {
|
||||
for (const auto& rule : rules) {
|
||||
if (!rule.isPersistent)
|
||||
continue;
|
||||
|
||||
PHLWORKSPACE PWORKSPACE = nullptr;
|
||||
if (pWorkspace) {
|
||||
if (pWorkspace->matchesStaticSelector(rule.workspaceString))
|
||||
PWORKSPACE = pWorkspace;
|
||||
else
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto PMONITOR = getMonitorFromString(rule.monitor);
|
||||
|
||||
if (!rule.monitor.empty() && !PMONITOR)
|
||||
continue; // don't do anything yet, as the monitor is not yet present.
|
||||
|
||||
if (!PWORKSPACE) {
|
||||
WORKSPACEID id = rule.workspaceId;
|
||||
std::string wsname = rule.workspaceName;
|
||||
|
||||
if (id == WORKSPACE_INVALID) {
|
||||
const auto R = getWorkspaceIDNameFromString(rule.workspaceString);
|
||||
id = R.id;
|
||||
wsname = R.name;
|
||||
}
|
||||
|
||||
if (id == WORKSPACE_INVALID) {
|
||||
Debug::log(ERR, "ensurePersistentWorkspacesPresent: couldn't resolve id for workspace {}", rule.workspaceString);
|
||||
continue;
|
||||
}
|
||||
PWORKSPACE = getWorkspaceByID(id);
|
||||
if (!PWORKSPACE)
|
||||
createNewWorkspace(id, PMONITOR ? PMONITOR->ID : m_pLastMonitor->ID, wsname, false);
|
||||
}
|
||||
|
||||
if (PWORKSPACE)
|
||||
PWORKSPACE->m_bPersistent = true;
|
||||
|
||||
if (!PMONITOR) {
|
||||
Debug::log(ERR, "ensurePersistentWorkspacesPresent: couldn't resolve monitor for {}, skipping", rule.monitor);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (PWORKSPACE) {
|
||||
WORKSPACEID id = rule.workspaceId;
|
||||
std::string wsname = rule.workspaceName;
|
||||
if (id == WORKSPACE_INVALID) {
|
||||
const auto R = getWorkspaceIDNameFromString(rule.workspaceString);
|
||||
id = R.id;
|
||||
wsname = R.name;
|
||||
}
|
||||
|
||||
if (id == WORKSPACE_INVALID) {
|
||||
Debug::log(ERR, "ensurePersistentWorkspacesPresent: couldn't resolve id for workspace {}", rule.workspaceString);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (const auto PWORKSPACE = getWorkspaceByID(id); PWORKSPACE) {
|
||||
if (PWORKSPACE->m_pMonitor == PMONITOR) {
|
||||
Debug::log(LOG, "ensurePersistentWorkspacesPresent: workspace persistent {} already on {}", rule.workspaceString, PMONITOR->szName);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -3125,6 +3060,8 @@ void CCompositor::ensurePersistentWorkspacesPresent(const std::vector<SWorkspace
|
||||
moveWorkspaceToMonitor(PWORKSPACE, PMONITOR);
|
||||
continue;
|
||||
}
|
||||
|
||||
createNewWorkspace(id, PMONITOR ? PMONITOR : m_pLastMonitor.lock(), wsname, false);
|
||||
}
|
||||
|
||||
// cleanup old
|
||||
|
@@ -1,12 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include <list>
|
||||
#include <sys/resource.h>
|
||||
|
||||
#include "defines.hpp"
|
||||
#include "managers/XWaylandManager.hpp"
|
||||
#include "managers/KeybindManager.hpp"
|
||||
#include "managers/SessionLockManager.hpp"
|
||||
#include "desktop/Window.hpp"
|
||||
#include "protocols/types/ColorManagement.hpp"
|
||||
#include "helpers/memory/Memory.hpp"
|
||||
|
||||
#include <aquamarine/backend/Backend.hpp>
|
||||
#include <aquamarine/output/Output.hpp>
|
||||
@@ -25,8 +28,8 @@ class CCompositor {
|
||||
CCompositor(bool onlyConfig = false);
|
||||
~CCompositor();
|
||||
|
||||
wl_display* m_sWLDisplay = nullptr;
|
||||
wl_event_loop* m_sWLEventLoop = nullptr;
|
||||
wl_display* m_sWLDisplay;
|
||||
wl_event_loop* m_sWLEventLoop;
|
||||
int m_iDRMFD = -1;
|
||||
bool m_bInitialized = false;
|
||||
SP<Aquamarine::CBackend> m_pAqBackend;
|
||||
@@ -52,6 +55,8 @@ class CCompositor {
|
||||
void startCompositor();
|
||||
void stopCompositor();
|
||||
void cleanup();
|
||||
void createLockFile();
|
||||
void removeLockFile();
|
||||
void bumpNofile();
|
||||
void restoreNofile();
|
||||
|
||||
@@ -81,7 +86,7 @@ class CCompositor {
|
||||
PHLMONITOR getMonitorFromCursor();
|
||||
PHLMONITOR getMonitorFromVector(const Vector2D&);
|
||||
void removeWindowFromVectorSafe(PHLWINDOW);
|
||||
void focusWindow(PHLWINDOW, SP<CWLSurfaceResource> pSurface = nullptr, bool preserveFocusHistory = false);
|
||||
void focusWindow(PHLWINDOW, SP<CWLSurfaceResource> pSurface = nullptr);
|
||||
void focusSurface(SP<CWLSurfaceResource>, PHLWINDOW pWindowOwner = nullptr);
|
||||
bool monitorExists(PHLMONITOR);
|
||||
PHLWINDOW vectorToWindowUnified(const Vector2D&, uint8_t properties, PHLWINDOW pIgnoreWindow = nullptr);
|
||||
@@ -103,8 +108,8 @@ class CCompositor {
|
||||
void cleanupFadingOut(const MONITORID& monid);
|
||||
PHLWINDOW getWindowInDirection(PHLWINDOW, char);
|
||||
PHLWINDOW getWindowInDirection(const CBox& box, PHLWORKSPACE pWorkspace, char dir, PHLWINDOW ignoreWindow = nullptr, bool useVectorAngles = false);
|
||||
PHLWINDOW getWindowCycle(PHLWINDOW cur, bool focusableOnly = false, std::optional<bool> floating = std::nullopt, bool visible = false, bool prev = false);
|
||||
PHLWINDOW getWindowCycleHist(PHLWINDOWREF cur, bool focusableOnly = false, std::optional<bool> floating = std::nullopt, bool visible = false, bool next = false);
|
||||
PHLWINDOW getNextWindowOnWorkspace(PHLWINDOW, bool focusableOnly = false, std::optional<bool> floating = {}, bool visible = false);
|
||||
PHLWINDOW getPrevWindowOnWorkspace(PHLWINDOW, bool focusableOnly = false, std::optional<bool> floating = {}, bool visible = false);
|
||||
WORKSPACEID getNextAvailableNamedWorkspace();
|
||||
bool isPointOnAnyMonitor(const Vector2D&);
|
||||
bool isPointOnReservedArea(const Vector2D& point, const PHLMONITOR monitor = nullptr);
|
||||
@@ -147,12 +152,12 @@ class CCompositor {
|
||||
void setPreferredTransformForSurface(SP<CWLSurfaceResource> pSurface, wl_output_transform transform);
|
||||
void updateSuspendedStates();
|
||||
void onNewMonitor(SP<Aquamarine::IOutput> output);
|
||||
void ensurePersistentWorkspacesPresent(const std::vector<SWorkspaceRule>& rules, PHLWORKSPACE pWorkspace = nullptr);
|
||||
void ensurePersistentWorkspacesPresent(const std::vector<SWorkspaceRule>& rules);
|
||||
|
||||
NColorManagement::SImageDescription getPreferredImageDescription();
|
||||
bool shouldChangePreferredImageDescription();
|
||||
SImageDescription getPreferredImageDescription();
|
||||
bool shouldChangePreferredImageDescription();
|
||||
|
||||
std::string explicitConfigPath;
|
||||
std::string explicitConfigPath;
|
||||
|
||||
private:
|
||||
void initAllSignals();
|
||||
@@ -161,13 +166,11 @@ class CCompositor {
|
||||
void setRandomSplash();
|
||||
void initManagers(eManagersInitStage stage);
|
||||
void prepareFallbackOutput();
|
||||
void createLockFile();
|
||||
void removeLockFile();
|
||||
void setMallocThreshold();
|
||||
bool isWindowAvailableForCycle(PHLWINDOW pWindow, PHLWINDOW w, bool focusableOnly, std::optional<bool> floating, bool anyWorkspace = false);
|
||||
|
||||
uint64_t m_iHyprlandPID = 0;
|
||||
wl_event_source* m_critSigSource = nullptr;
|
||||
rlimit m_sOriginalNofile = {};
|
||||
rlimit m_sOriginalNofile = {0};
|
||||
};
|
||||
|
||||
inline UP<CCompositor> g_pCompositor;
|
||||
|
@@ -11,7 +11,7 @@ enum eConfigValueDataTypes : int8_t {
|
||||
|
||||
class ICustomConfigValueData {
|
||||
public:
|
||||
virtual ~ICustomConfigValueData() = default;
|
||||
virtual ~ICustomConfigValueData() = 0;
|
||||
|
||||
virtual eConfigValueDataTypes getDataType() = 0;
|
||||
|
||||
|
@@ -253,98 +253,98 @@ inline static const std::vector<SConfigOptionDescription> CONFIG_OPTIONS = {
|
||||
*/
|
||||
|
||||
SConfigOptionDescription{
|
||||
.value = "decoration:blur:enabled",
|
||||
.value = "blur:enabled",
|
||||
.description = "enable kawase window background blur",
|
||||
.type = CONFIG_OPTION_BOOL,
|
||||
.data = SConfigOptionDescription::SBoolData{true},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "decoration:blur:size",
|
||||
.value = "blur:size",
|
||||
.description = "blur size (distance)",
|
||||
.type = CONFIG_OPTION_INT,
|
||||
.data = SConfigOptionDescription::SRangeData{8, 0, 100},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "decoration:blur:passes",
|
||||
.value = "blur:passes",
|
||||
.description = "the amount of passes to perform",
|
||||
.type = CONFIG_OPTION_INT,
|
||||
.data = SConfigOptionDescription::SRangeData{1, 0, 10},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "decoration:blur:ignore_opacity",
|
||||
.value = "blur:ignore_opacity",
|
||||
.description = "make the blur layer ignore the opacity of the window",
|
||||
.type = CONFIG_OPTION_BOOL,
|
||||
.data = SConfigOptionDescription::SBoolData{true},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "decoration:blur:new_optimizations",
|
||||
.value = "blur:new_optimizations",
|
||||
.description = "whether to enable further optimizations to the blur. Recommended to leave on, as it will massively improve performance.",
|
||||
.type = CONFIG_OPTION_BOOL,
|
||||
.data = SConfigOptionDescription::SBoolData{true},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "decoration:blur:xray",
|
||||
.value = "blur:xray",
|
||||
.description = "if enabled, floating windows will ignore tiled windows in their blur. Only available if blur_new_optimizations is true. Will reduce overhead on floating "
|
||||
"blur significantly.",
|
||||
.type = CONFIG_OPTION_BOOL,
|
||||
.data = SConfigOptionDescription::SBoolData{false},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "decoration:blur:noise",
|
||||
.value = "blur:noise",
|
||||
.description = "how much noise to apply. [0.0 - 1.0]",
|
||||
.type = CONFIG_OPTION_FLOAT,
|
||||
.data = SConfigOptionDescription::SFloatData{0.0117, 0, 1},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "decoration:blur:contrast",
|
||||
.value = "blur:contrast",
|
||||
.description = "contrast modulation for blur. [0.0 - 2.0]",
|
||||
.type = CONFIG_OPTION_FLOAT,
|
||||
.data = SConfigOptionDescription::SFloatData{0.8916, 0, 2},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "decoration:blur:brightness",
|
||||
.value = "blur:brightness",
|
||||
.description = "brightness modulation for blur. [0.0 - 2.0]",
|
||||
.type = CONFIG_OPTION_FLOAT,
|
||||
.data = SConfigOptionDescription::SFloatData{0.8172, 0, 2},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "decoration:blur:vibrancy",
|
||||
.value = "blur:vibrancy",
|
||||
.description = "Increase saturation of blurred colors. [0.0 - 1.0]",
|
||||
.type = CONFIG_OPTION_FLOAT,
|
||||
.data = SConfigOptionDescription::SFloatData{0.1696, 0, 1},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "decoration:blur:vibrancy_darkness",
|
||||
.value = "blur:vibrancy_darkness",
|
||||
.description = "How strong the effect of vibrancy is on dark areas . [0.0 - 1.0]",
|
||||
.type = CONFIG_OPTION_FLOAT,
|
||||
.data = SConfigOptionDescription::SFloatData{0, 0, 1},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "decoration:blur:special",
|
||||
.value = "blur:special",
|
||||
.description = "whether to blur behind the special workspace (note: expensive)",
|
||||
.type = CONFIG_OPTION_BOOL,
|
||||
.data = SConfigOptionDescription::SBoolData{false},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "decoration:blur:popups",
|
||||
.value = "blur:popups",
|
||||
.description = "whether to blur popups (e.g. right-click menus)",
|
||||
.type = CONFIG_OPTION_BOOL,
|
||||
.data = SConfigOptionDescription::SBoolData{false},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "decoration:blur:popups_ignorealpha",
|
||||
.value = "blur:popups_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},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "decoration:blur:input_methods",
|
||||
.value = "blur:input_methods",
|
||||
.description = "whether to blur input methods (e.g. fcitx5)",
|
||||
.type = CONFIG_OPTION_BOOL,
|
||||
.data = SConfigOptionDescription::SBoolData{false},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "decoration:blur:input_methods_ignorealpha",
|
||||
.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},
|
||||
@@ -501,12 +501,6 @@ inline static const std::vector<SConfigOptionDescription> CONFIG_OPTIONS = {
|
||||
.type = CONFIG_OPTION_INT,
|
||||
.data = SConfigOptionDescription::SRangeData{1, 0, 3},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "input:follow_mouse_threshold",
|
||||
.description = "The smallest distance in logical pixels the mouse needs to travel for the window under it to get focused. Works only with follow_mouse = 1.",
|
||||
.type = CONFIG_OPTION_FLOAT,
|
||||
.data = SConfigOptionDescription::SFloatData{},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "input:focus_on_close",
|
||||
.description = "Controls the window focus behavior when a window is closed. When set to 0, focus will shift to the next window candidate. When set to 1, focus will shift "
|
||||
@@ -608,18 +602,6 @@ inline static const std::vector<SConfigOptionDescription> CONFIG_OPTIONS = {
|
||||
.type = CONFIG_OPTION_BOOL,
|
||||
.data = SConfigOptionDescription::SBoolData{false},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "input:touchpad:flip_x",
|
||||
.description = "Inverts the horizontal movement of the touchpad",
|
||||
.type = CONFIG_OPTION_BOOL,
|
||||
.data = SConfigOptionDescription::SBoolData{false},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "input:touchpad:flip_y",
|
||||
.description = "Inverts the vertical movement of the touchpad",
|
||||
.type = CONFIG_OPTION_BOOL,
|
||||
.data = SConfigOptionDescription::SBoolData{false},
|
||||
},
|
||||
|
||||
/*
|
||||
* input:touchdevice:
|
||||
@@ -827,25 +809,25 @@ inline static const std::vector<SConfigOptionDescription> CONFIG_OPTIONS = {
|
||||
.data = SConfigOptionDescription::SBoolData{true},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "group:col.border_active",
|
||||
.value = "general:col.border_active",
|
||||
.description = "border color for inactive windows",
|
||||
.type = CONFIG_OPTION_GRADIENT,
|
||||
.data = SConfigOptionDescription::SGradientData{"0x66ffff00"},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "group:col.border_inactive",
|
||||
.value = "general:col.border_inactive",
|
||||
.description = "border color for the active window",
|
||||
.type = CONFIG_OPTION_GRADIENT,
|
||||
.data = SConfigOptionDescription::SGradientData{"0x66777700"},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "group:col.border_locked_inactive",
|
||||
.value = "general:col.border_locked_active",
|
||||
.description = "inactive border color for window that cannot be added to a group (see denywindowfromgroup dispatcher)",
|
||||
.type = CONFIG_OPTION_GRADIENT,
|
||||
.data = SConfigOptionDescription::SGradientData{"0x66ff5500"},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "group:col.border_locked_active",
|
||||
.value = "general:col.border_locked_inactive",
|
||||
.description = "active border color for window that cannot be added to a group",
|
||||
.type = CONFIG_OPTION_GRADIENT,
|
||||
.data = SConfigOptionDescription::SGradientData{"0x66775500"},
|
||||
@@ -901,7 +883,7 @@ inline static const std::vector<SConfigOptionDescription> CONFIG_OPTIONS = {
|
||||
.value = "group:groupbar:gradients",
|
||||
.description = "enables gradients",
|
||||
.type = CONFIG_OPTION_BOOL,
|
||||
.data = SConfigOptionDescription::SBoolData{false},
|
||||
.data = SConfigOptionDescription::SBoolData{true},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "group:groupbar:height",
|
||||
@@ -909,12 +891,6 @@ inline static const std::vector<SConfigOptionDescription> CONFIG_OPTIONS = {
|
||||
.type = CONFIG_OPTION_INT,
|
||||
.data = SConfigOptionDescription::SRangeData{14, 1, 64},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "group:groupbar:indicator_height",
|
||||
.description = "height of the groupbar indicator",
|
||||
.type = CONFIG_OPTION_INT,
|
||||
.data = SConfigOptionDescription::SRangeData{3, 1, 64},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "group:groupbar:stacked",
|
||||
.description = "render the groupbar as a vertical stack",
|
||||
@@ -939,30 +915,6 @@ inline static const std::vector<SConfigOptionDescription> CONFIG_OPTIONS = {
|
||||
.type = CONFIG_OPTION_BOOL,
|
||||
.data = SConfigOptionDescription::SBoolData{true},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "group:groupbar:rounding",
|
||||
.description = "how much to round the groupbar",
|
||||
.type = CONFIG_OPTION_INT,
|
||||
.data = SConfigOptionDescription::SRangeData{1, 0, 20},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "group:groupbar:gradient_rounding",
|
||||
.description = "how much to round the groupbar gradient",
|
||||
.type = CONFIG_OPTION_INT,
|
||||
.data = SConfigOptionDescription::SRangeData{1, 0, 20},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "group:groupbar:round_only_edges",
|
||||
.description = "if yes, will only round at the groupbar edges",
|
||||
.type = CONFIG_OPTION_BOOL,
|
||||
.data = SConfigOptionDescription::SBoolData{true},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "group:groupbar:gradient_round_only_edges",
|
||||
.description = "if yes, will only round at the groupbar gradient edges",
|
||||
.type = CONFIG_OPTION_BOOL,
|
||||
.data = SConfigOptionDescription::SBoolData{true},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "group:groupbar:text_color",
|
||||
.description = "controls the group bar text color",
|
||||
@@ -993,18 +945,6 @@ inline static const std::vector<SConfigOptionDescription> CONFIG_OPTIONS = {
|
||||
.type = CONFIG_OPTION_COLOR,
|
||||
.data = SConfigOptionDescription::SColorData{0x66775500},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "group:groupbar:gaps_out",
|
||||
.description = "gap between gradients and window",
|
||||
.type = CONFIG_OPTION_INT,
|
||||
.data = SConfigOptionDescription::SRangeData{2, 0, 20},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "group:groupbar:gaps_in",
|
||||
.description = "gap between gradients",
|
||||
.type = CONFIG_OPTION_INT,
|
||||
.data = SConfigOptionDescription::SRangeData{2, 0, 20},
|
||||
},
|
||||
|
||||
/*
|
||||
* misc:
|
||||
@@ -1054,9 +994,9 @@ inline static const std::vector<SConfigOptionDescription> CONFIG_OPTIONS = {
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "misc:vrr",
|
||||
.description = " controls the VRR (Adaptive Sync) of your monitors. 0 - off, 1 - on, 2 - fullscreen only, 3 - fullscreen with game or video content type [0/1/2/3]",
|
||||
.description = " controls the VRR (Adaptive Sync) of your monitors. 0 - off, 1 - on, 2 - fullscreen only [0/1/2]",
|
||||
.type = CONFIG_OPTION_INT,
|
||||
.data = SConfigOptionDescription::SRangeData{.value = 0, .min = 0, .max = 3},
|
||||
.data = SConfigOptionDescription::SRangeData{0, 0, 2},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "misc:mouse_move_enables_dpms",
|
||||
@@ -1211,12 +1151,6 @@ inline static const std::vector<SConfigOptionDescription> CONFIG_OPTIONS = {
|
||||
.type = CONFIG_OPTION_INT,
|
||||
.data = SConfigOptionDescription::SRangeData{1000, 0, 5000},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "misc:enable_anr_dialog",
|
||||
.description = "whether to enable the ANR (app not responding) dialog when your apps hang",
|
||||
.type = CONFIG_OPTION_BOOL,
|
||||
.data = SConfigOptionDescription::SBoolData{true},
|
||||
},
|
||||
|
||||
/*
|
||||
* binds:
|
||||
@@ -1270,7 +1204,7 @@ inline static const std::vector<SConfigOptionDescription> CONFIG_OPTIONS = {
|
||||
.value = "binds:movefocus_cycles_fullscreen",
|
||||
.description = "If enabled, when on a fullscreen window, movefocus will cycle fullscreen, if not, it will move the focus in a direction.",
|
||||
.type = CONFIG_OPTION_BOOL,
|
||||
.data = SConfigOptionDescription::SBoolData{false},
|
||||
.data = SConfigOptionDescription::SBoolData{true},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "binds:movefocus_cycles_groupfirst",
|
||||
@@ -1319,12 +1253,6 @@ inline static const std::vector<SConfigOptionDescription> CONFIG_OPTIONS = {
|
||||
.type = CONFIG_OPTION_BOOL,
|
||||
.data = SConfigOptionDescription::SBoolData{false},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "xwayland:create_abstract_socket",
|
||||
.description = "Create the abstract Unix domain socket for XWayland",
|
||||
.type = CONFIG_OPTION_BOOL,
|
||||
.data = SConfigOptionDescription::SBoolData{false},
|
||||
},
|
||||
|
||||
/*
|
||||
* opengl:
|
||||
@@ -1336,6 +1264,13 @@ inline static const std::vector<SConfigOptionDescription> CONFIG_OPTIONS = {
|
||||
.type = CONFIG_OPTION_BOOL,
|
||||
.data = SConfigOptionDescription::SBoolData{true},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "opengl:force_introspection",
|
||||
.description = "forces introspection at all times. Introspection is aimed at reducing GPU usage in certain cases, but might cause graphical glitches on nvidia. 0 - "
|
||||
"nothing, 1 - force always on, 2 - force always on if nvidia",
|
||||
.type = CONFIG_OPTION_INT,
|
||||
.data = SConfigOptionDescription::SRangeData{2, 0, 2},
|
||||
},
|
||||
|
||||
/*
|
||||
* render:
|
||||
@@ -1356,9 +1291,9 @@ inline static const std::vector<SConfigOptionDescription> CONFIG_OPTIONS = {
|
||||
SConfigOptionDescription{
|
||||
.value = "render:direct_scanout",
|
||||
.description = "Enables direct scanout. Direct scanout attempts to reduce lag when there is only one fullscreen application on a screen (e.g. game). It is also "
|
||||
"recommended to set this to false if the fullscreen application shows graphical glitches. 0 - off, 1 - on, 2 - auto (on with content type 'game')",
|
||||
.type = CONFIG_OPTION_INT,
|
||||
.data = SConfigOptionDescription::SRangeData{.value = 0, .min = 0, .max = 2},
|
||||
"recommended to set this to false if the fullscreen application shows graphical glitches.",
|
||||
.type = CONFIG_OPTION_BOOL,
|
||||
.data = SConfigOptionDescription::SBoolData{false},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "render:expand_undersized_textures",
|
||||
@@ -1379,14 +1314,8 @@ inline static const std::vector<SConfigOptionDescription> CONFIG_OPTIONS = {
|
||||
.data = SConfigOptionDescription::SRangeData{2, 0, 2},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "render:cm_fs_passthrough",
|
||||
.description = "Passthrough color settings for fullscreen apps when possible",
|
||||
.type = CONFIG_OPTION_INT,
|
||||
.data = SConfigOptionDescription::SRangeData{.value = 2, .min = 0, .max = 2},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "render:cm_enabled",
|
||||
.description = "Enable Color Management pipelines (requires restart to fully take effect)",
|
||||
.value = "render:allow_early_buffer_release",
|
||||
.description = "Allow early buffer release event. Fixes stuttering and missing frames for some apps. May cause graphical glitches and memory leaks in others",
|
||||
.type = CONFIG_OPTION_BOOL,
|
||||
.data = SConfigOptionDescription::SBoolData{true},
|
||||
},
|
||||
@@ -1395,18 +1324,24 @@ inline static const std::vector<SConfigOptionDescription> CONFIG_OPTIONS = {
|
||||
* cursor:
|
||||
*/
|
||||
|
||||
SConfigOptionDescription{
|
||||
.value = "cursor:use_nearest_neighbor",
|
||||
.description = "sync xcursor theme with gsettings, it applies cursor-theme and cursor-size on theme load to gsettings making most CSD gtk based clients use same xcursor "
|
||||
"theme and size.",
|
||||
.type = CONFIG_OPTION_BOOL,
|
||||
.data = SConfigOptionDescription::SBoolData{true},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "cursor:no_hardware_cursors",
|
||||
.description = "disables hardware cursors. Auto = disable when tearing",
|
||||
.description = "disables hardware cursors",
|
||||
.type = CONFIG_OPTION_CHOICE,
|
||||
.data = SConfigOptionDescription::SChoiceData{0, "Disabled,Enabled,Auto"},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "cursor:no_break_fs_vrr",
|
||||
.description = "disables scheduling new frames on cursor movement for fullscreen apps with VRR enabled to avoid framerate spikes (may require no_hardware_cursors = true) "
|
||||
"0 - off, 1 - on, 2 - auto (on with content type 'game')",
|
||||
.type = CONFIG_OPTION_INT,
|
||||
.data = SConfigOptionDescription::SRangeData{.value = 2, .min = 0, .max = 2},
|
||||
.description = "disables scheduling new frames on cursor movement for fullscreen apps with VRR enabled to avoid framerate spikes (requires no_hardware_cursors = true)",
|
||||
.type = CONFIG_OPTION_BOOL,
|
||||
.data = SConfigOptionDescription::SBoolData{false},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "cursor:min_refresh_rate",
|
||||
@@ -1486,35 +1421,6 @@ inline static const std::vector<SConfigOptionDescription> CONFIG_OPTIONS = {
|
||||
.type = CONFIG_OPTION_BOOL,
|
||||
.data = SConfigOptionDescription::SBoolData{false},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "cursor:sync_gsettings_theme",
|
||||
.description = "sync xcursor theme with gsettings, it applies cursor-theme and cursor-size on theme load to gsettings making most CSD gtk based clients use same xcursor "
|
||||
"theme and size.",
|
||||
.type = CONFIG_OPTION_BOOL,
|
||||
.data = SConfigOptionDescription::SBoolData{true},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "cursor:warp_back_after_non_mouse_input",
|
||||
.description = "warp the cursor back to where it was after using a non-mouse input to move it, and then returning back to mouse.",
|
||||
.type = CONFIG_OPTION_BOOL,
|
||||
.data = SConfigOptionDescription::SBoolData{false},
|
||||
},
|
||||
|
||||
/*
|
||||
* ecosystem:
|
||||
*/
|
||||
SConfigOptionDescription{
|
||||
.value = "ecosystem:no_update_news",
|
||||
.description = "disable the popup that shows up when you update hyprland to a new version.",
|
||||
.type = CONFIG_OPTION_BOOL,
|
||||
.data = SConfigOptionDescription::SBoolData{false},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "ecosystem:no_donation_nag",
|
||||
.description = "disable the popup that shows up twice a year encouraging to donate.",
|
||||
.type = CONFIG_OPTION_BOOL,
|
||||
.data = SConfigOptionDescription::SBoolData{false},
|
||||
},
|
||||
|
||||
/*
|
||||
* debug:
|
||||
@@ -1598,24 +1504,6 @@ inline static const std::vector<SConfigOptionDescription> CONFIG_OPTIONS = {
|
||||
.type = CONFIG_OPTION_BOOL,
|
||||
.data = SConfigOptionDescription::SBoolData{true},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "debug:log_damage",
|
||||
.description = "enables logging the damage.",
|
||||
.type = CONFIG_OPTION_BOOL,
|
||||
.data = SConfigOptionDescription::SBoolData{false},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "debug:pass",
|
||||
.description = "enables render pass debugging.",
|
||||
.type = CONFIG_OPTION_BOOL,
|
||||
.data = SConfigOptionDescription::SBoolData{false},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "debug:full_cm_proto",
|
||||
.description = "claims support for all cm proto features (requires restart)",
|
||||
.type = CONFIG_OPTION_BOOL,
|
||||
.data = SConfigOptionDescription::SBoolData{false},
|
||||
},
|
||||
|
||||
/*
|
||||
* dwindle:
|
||||
@@ -1776,16 +1664,22 @@ inline static const std::vector<SConfigOptionDescription> CONFIG_OPTIONS = {
|
||||
.type = CONFIG_OPTION_BOOL,
|
||||
.data = SConfigOptionDescription::SBoolData{true},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "experimental:wide_color_gamut",
|
||||
.description = "force wide color gamut for all supported outputs",
|
||||
.type = CONFIG_OPTION_BOOL,
|
||||
.data = SConfigOptionDescription::SBoolData{false},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "experimental:hdr",
|
||||
.description = "force static hdr for all supported outputs",
|
||||
.type = CONFIG_OPTION_BOOL,
|
||||
.data = SConfigOptionDescription::SBoolData{false},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "experimental:xx_color_management_v4",
|
||||
.description = "enable color management protocol",
|
||||
.type = CONFIG_OPTION_BOOL,
|
||||
.data = SConfigOptionDescription::SBoolData{false},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "master:always_keep_position",
|
||||
.description = "whether to keep the master window in its configured position when there are no slave windows",
|
||||
.type = CONFIG_OPTION_BOOL,
|
||||
.data = SConfigOptionDescription::SBoolData{false},
|
||||
},
|
||||
};
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -138,27 +138,6 @@ struct SFirstExecRequest {
|
||||
bool withRules = false;
|
||||
};
|
||||
|
||||
struct SFloatCache {
|
||||
size_t hash;
|
||||
|
||||
SFloatCache(PHLWINDOW window) {
|
||||
hash = std::hash<std::string>{}(window->m_szClass) ^ (std::hash<std::string>{}(window->m_szTitle) << 1);
|
||||
}
|
||||
|
||||
bool operator==(const SFloatCache& other) const {
|
||||
return hash == other.hash;
|
||||
}
|
||||
};
|
||||
|
||||
namespace std {
|
||||
template <>
|
||||
struct hash<SFloatCache> {
|
||||
size_t operator()(const SFloatCache& id) const {
|
||||
return id.hash;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
class CConfigManager {
|
||||
public:
|
||||
CConfigManager();
|
||||
@@ -210,7 +189,7 @@ class CConfigManager {
|
||||
void ensureMonitorStatus();
|
||||
void ensureVRR(PHLMONITOR pMonitor = nullptr);
|
||||
|
||||
bool shouldUseSoftwareCursors(PHLMONITOR pMonitor);
|
||||
bool shouldUseSoftwareCursors();
|
||||
void updateWatcher();
|
||||
|
||||
std::string parseKeyword(const std::string&, const std::string&);
|
||||
@@ -225,35 +204,66 @@ class CConfigManager {
|
||||
std::string getErrors();
|
||||
|
||||
// keywords
|
||||
std::optional<std::string> handleRawExec(const std::string&, const std::string&);
|
||||
std::optional<std::string> handleExec(const std::string&, const std::string&);
|
||||
std::optional<std::string> handleExecOnce(const std::string&, const std::string&);
|
||||
std::optional<std::string> handleExecRawOnce(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> 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> handleExec(const std::string&, const std::string&);
|
||||
std::optional<std::string> handleExecOnce(const std::string&, const std::string&);
|
||||
std::optional<std::string> handleExecRawOnce(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;
|
||||
|
||||
bool m_bWantsMonitorReload = false;
|
||||
bool m_bNoMonitorReload = false;
|
||||
bool isLaunchingExecOnce = false; // For exec-once to skip initial ws tracking
|
||||
bool m_bLastConfigVerificationWasSuccessful = true;
|
||||
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; }},
|
||||
};
|
||||
|
||||
void storeFloatingSize(PHLWINDOW window, const Vector2D& size);
|
||||
std::optional<Vector2D> getStoredFloatingSize(PHLWINDOW window);
|
||||
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 = {
|
||||
{"roundingpower", [](const PHLWINDOW& pWindow) { return &pWindow->m_sWindowData.roundingPower; }},
|
||||
{"scrollmouse", [](const PHLWINDOW& pWindow) { return &pWindow->m_sWindowData.scrollMouse; }},
|
||||
{"scrolltouchpad", [](const PHLWINDOW& pWindow) { return &pWindow->m_sWindowData.scrollTouchpad; }}};
|
||||
|
||||
bool m_bWantsMonitorReload = false;
|
||||
bool m_bNoMonitorReload = false;
|
||||
bool isLaunchingExecOnce = false; // For exec-once to skip initial ws tracking
|
||||
bool m_bLastConfigVerificationWasSuccessful = true;
|
||||
|
||||
private:
|
||||
UP<Hyprlang::CConfig> m_pConfig;
|
||||
@@ -287,26 +297,14 @@ class CConfigManager {
|
||||
std::vector<std::pair<std::string, std::string>> m_vFailedPluginConfigValues; // for plugin values of unloaded plugins
|
||||
std::string m_szConfigErrors = "";
|
||||
|
||||
uint32_t m_configValueNumber = 0;
|
||||
|
||||
// internal methods
|
||||
void updateBlurredLS(const std::string&, const bool);
|
||||
void setDefaultAnimationVars();
|
||||
std::optional<std::string> resetHLConfig();
|
||||
std::optional<std::string> generateConfig(std::string configPath);
|
||||
std::optional<std::string> verifyConfigExists();
|
||||
void postConfigReload(const Hyprlang::CParseResult& result);
|
||||
SWorkspaceRule mergeWorkspaceRules(const SWorkspaceRule&, const SWorkspaceRule&);
|
||||
|
||||
void registerConfigVar(const char* name, const Hyprlang::INT& val);
|
||||
void registerConfigVar(const char* name, const Hyprlang::FLOAT& val);
|
||||
void registerConfigVar(const char* name, const Hyprlang::VEC2& val);
|
||||
void registerConfigVar(const char* name, const Hyprlang::STRING& val);
|
||||
void registerConfigVar(const char* name, Hyprlang::CUSTOMTYPE&& val);
|
||||
|
||||
std::unordered_map<SFloatCache, Vector2D> m_mStoredFloatingSizes;
|
||||
|
||||
friend struct SConfigOptionDescription;
|
||||
void updateBlurredLS(const std::string&, const bool);
|
||||
void setDefaultAnimationVars();
|
||||
std::optional<std::string> resetHLConfig();
|
||||
std::optional<std::string> generateConfig(std::string configPath);
|
||||
std::optional<std::string> verifyConfigExists();
|
||||
void postConfigReload(const Hyprlang::CParseResult& result);
|
||||
SWorkspaceRule mergeWorkspaceRules(const SWorkspaceRule&, const SWorkspaceRule&);
|
||||
};
|
||||
|
||||
inline UP<CConfigManager> g_pConfigManager;
|
||||
|
@@ -6,24 +6,27 @@
|
||||
#include <unistd.h>
|
||||
#include <filesystem>
|
||||
|
||||
using namespace Hyprutils::OS;
|
||||
|
||||
CConfigWatcher::CConfigWatcher() : m_inotifyFd(inotify_init()) {
|
||||
if (!m_inotifyFd.isValid()) {
|
||||
if (m_inotifyFd < 0) {
|
||||
Debug::log(ERR, "CConfigWatcher couldn't open an inotify node. Config will not be automatically reloaded");
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: make CFileDescriptor take F_GETFL, F_SETFL
|
||||
const int FLAGS = fcntl(m_inotifyFd.get(), F_GETFL, 0);
|
||||
if (fcntl(m_inotifyFd.get(), F_SETFL, FLAGS | O_NONBLOCK) < 0) {
|
||||
const int FLAGS = fcntl(m_inotifyFd, F_GETFL, 0);
|
||||
if (fcntl(m_inotifyFd, F_SETFL, FLAGS | O_NONBLOCK) < 0) {
|
||||
Debug::log(ERR, "CConfigWatcher couldn't non-block inotify node. Config will not be automatically reloaded");
|
||||
m_inotifyFd.reset();
|
||||
close(m_inotifyFd);
|
||||
m_inotifyFd = -1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
CFileDescriptor& CConfigWatcher::getInotifyFD() {
|
||||
CConfigWatcher::~CConfigWatcher() {
|
||||
if (m_inotifyFd >= 0)
|
||||
close(m_inotifyFd);
|
||||
}
|
||||
|
||||
int CConfigWatcher::getInotifyFD() {
|
||||
return m_inotifyFd;
|
||||
}
|
||||
|
||||
@@ -36,7 +39,7 @@ void CConfigWatcher::setWatchList(const std::vector<std::string>& paths) {
|
||||
|
||||
// cleanup old paths
|
||||
for (auto& watch : m_watches) {
|
||||
inotify_rm_watch(m_inotifyFd.get(), watch.wd);
|
||||
inotify_rm_watch(m_inotifyFd, watch.wd);
|
||||
}
|
||||
|
||||
m_watches.clear();
|
||||
@@ -44,7 +47,7 @@ void CConfigWatcher::setWatchList(const std::vector<std::string>& paths) {
|
||||
// add new paths
|
||||
for (const auto& path : paths) {
|
||||
m_watches.emplace_back(SInotifyWatch{
|
||||
.wd = inotify_add_watch(m_inotifyFd.get(), path.c_str(), IN_MODIFY | IN_DONT_FOLLOW),
|
||||
.wd = inotify_add_watch(m_inotifyFd, path.c_str(), IN_MODIFY | IN_DONT_FOLLOW),
|
||||
.file = path,
|
||||
});
|
||||
|
||||
@@ -53,7 +56,7 @@ void CConfigWatcher::setWatchList(const std::vector<std::string>& paths) {
|
||||
const auto IS_SYMLINK = std::filesystem::is_symlink(path, ec2);
|
||||
if (!ec && !ec2 && IS_SYMLINK) {
|
||||
m_watches.emplace_back(SInotifyWatch{
|
||||
.wd = inotify_add_watch(m_inotifyFd.get(), CANONICAL.c_str(), IN_MODIFY),
|
||||
.wd = inotify_add_watch(m_inotifyFd, CANONICAL.c_str(), IN_MODIFY),
|
||||
.file = path,
|
||||
});
|
||||
}
|
||||
@@ -66,7 +69,7 @@ void CConfigWatcher::setOnChange(const std::function<void(const SConfigWatchEven
|
||||
|
||||
void CConfigWatcher::onInotifyEvent() {
|
||||
inotify_event ev;
|
||||
while (read(m_inotifyFd.get(), &ev, sizeof(ev)) > 0) {
|
||||
while (read(m_inotifyFd, &ev, sizeof(ev)) > 0) {
|
||||
const auto WD = std::ranges::find_if(m_watches.begin(), m_watches.end(), [wd = ev.wd](const auto& e) { return e.wd == wd; });
|
||||
|
||||
if (WD == m_watches.end()) {
|
||||
|
@@ -3,21 +3,20 @@
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <functional>
|
||||
#include <hyprutils/os/FileDescriptor.hpp>
|
||||
|
||||
class CConfigWatcher {
|
||||
public:
|
||||
CConfigWatcher();
|
||||
~CConfigWatcher() = default;
|
||||
~CConfigWatcher();
|
||||
|
||||
struct SConfigWatchEvent {
|
||||
std::string file;
|
||||
};
|
||||
|
||||
Hyprutils::OS::CFileDescriptor& getInotifyFD();
|
||||
void setWatchList(const std::vector<std::string>& paths);
|
||||
void setOnChange(const std::function<void(const SConfigWatchEvent&)>& fn);
|
||||
void onInotifyEvent();
|
||||
int getInotifyFD();
|
||||
void setWatchList(const std::vector<std::string>& paths);
|
||||
void setOnChange(const std::function<void(const SConfigWatchEvent&)>& fn);
|
||||
void onInotifyEvent();
|
||||
|
||||
private:
|
||||
struct SInotifyWatch {
|
||||
@@ -27,7 +26,7 @@ class CConfigWatcher {
|
||||
|
||||
std::function<void(const SConfigWatchEvent&)> m_watchCallback;
|
||||
std::vector<SInotifyWatch> m_watches;
|
||||
Hyprutils::OS::CFileDescriptor m_inotifyFd;
|
||||
int m_inotifyFd = -1;
|
||||
};
|
||||
|
||||
inline UP<CConfigWatcher> g_pConfigWatcher = makeUnique<CConfigWatcher>();
|
||||
inline UP<CConfigWatcher> g_pConfigWatcher = makeUnique<CConfigWatcher>();
|
@@ -152,10 +152,10 @@ animations {
|
||||
# uncomment all if you wish to use that.
|
||||
# workspace = w[tv1], gapsout:0, gapsin:0
|
||||
# workspace = f[1], gapsout:0, gapsin:0
|
||||
# windowrule = bordersize 0, floating:0, onworkspace:w[tv1]
|
||||
# windowrule = rounding 0, floating:0, onworkspace:w[tv1]
|
||||
# windowrule = bordersize 0, floating:0, onworkspace:f[1]
|
||||
# windowrule = rounding 0, floating:0, onworkspace:f[1]
|
||||
# windowrulev2 = bordersize 0, floating:0, onworkspace:w[tv1]
|
||||
# windowrulev2 = rounding 0, floating:0, onworkspace:w[tv1]
|
||||
# windowrulev2 = bordersize 0, floating:0, onworkspace:f[1]
|
||||
# windowrulev2 = rounding 0, floating:0, onworkspace:f[1]
|
||||
|
||||
# See https://wiki.hyprland.org/Configuring/Dwindle-Layout/ for more
|
||||
dwindle {
|
||||
@@ -269,7 +269,7 @@ bindm = $mainMod, mouse:272, movewindow
|
||||
bindm = $mainMod, mouse:273, resizewindow
|
||||
|
||||
# Laptop multimedia keys for volume and LCD brightness
|
||||
bindel = ,XF86AudioRaiseVolume, exec, wpctl set-volume -l 1 @DEFAULT_AUDIO_SINK@ 5%+
|
||||
bindel = ,XF86AudioRaiseVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%+
|
||||
bindel = ,XF86AudioLowerVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%-
|
||||
bindel = ,XF86AudioMute, exec, wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle
|
||||
bindel = ,XF86AudioMicMute, exec, wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle
|
||||
@@ -289,12 +289,15 @@ bindl = , XF86AudioPrev, exec, playerctl previous
|
||||
# See https://wiki.hyprland.org/Configuring/Window-Rules/ for more
|
||||
# See https://wiki.hyprland.org/Configuring/Workspace-Rules/ for workspace rules
|
||||
|
||||
# Example windowrule
|
||||
# windowrule = float,class:^(kitty)$,title:^(kitty)$
|
||||
# Example windowrule v1
|
||||
# windowrule = float, ^(kitty)$
|
||||
|
||||
# Example windowrule v2
|
||||
# windowrulev2 = float,class:^(kitty)$,title:^(kitty)$
|
||||
|
||||
# Ignore maximize requests from apps. You'll probably like this.
|
||||
windowrule = suppressevent maximize, class:.*
|
||||
windowrulev2 = suppressevent maximize, class:.*
|
||||
|
||||
# Fix some dragging issues with XWayland
|
||||
windowrule = nofocus,class:^$,title:^$,xwayland:1,floating:1,fullscreen:0,pinned:0
|
||||
windowrulev2 = nofocus,class:^$,title:^$,xwayland:1,floating:1,fullscreen:0,pinned:0
|
||||
)#";
|
||||
|
@@ -25,7 +25,6 @@
|
||||
|
||||
#include <hyprutils/string/String.hpp>
|
||||
using namespace Hyprutils::String;
|
||||
using namespace Hyprutils::OS;
|
||||
#include <aquamarine/input/Input.hpp>
|
||||
|
||||
#include "../config/ConfigDataValues.hpp"
|
||||
@@ -264,8 +263,8 @@ std::string CHyprCtl::getWindowData(PHLWINDOW w, eHyprCtlOutputFormat format) {
|
||||
escapeJSONStrings(!w->m_pWorkspace ? "" : w->m_pWorkspace->m_szName), ((int)w->m_bIsFloating == 1 ? "true" : "false"), (w->m_bIsPseudotiled ? "true" : "false"),
|
||||
(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.get(),
|
||||
getFocusHistoryID(w), (g_pInputManager->isWindowInhibiting(w, false) ? "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), (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: "
|
||||
@@ -276,7 +275,7 @@ std::string CHyprCtl::getWindowData(PHLWINDOW w, eHyprCtlOutputFormat format) {
|
||||
(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.get(), getFocusHistoryID(w),
|
||||
(uint8_t)w->m_sFullscreenState.client, getGroupedData(w, format), getTagsData(w, format), (uintptr_t)w->m_pSwallowed.lock().get(), getFocusHistoryID(w),
|
||||
(int)g_pInputManager->isWindowInhibiting(w, false));
|
||||
}
|
||||
}
|
||||
@@ -319,17 +318,15 @@ std::string CHyprCtl::getWorkspaceData(PHLWORKSPACE w, eHyprCtlOutputFormat form
|
||||
"windows": {},
|
||||
"hasfullscreen": {},
|
||||
"lastwindow": "0x{:x}",
|
||||
"lastwindowtitle": "{}",
|
||||
"ispersistent": {}
|
||||
"lastwindowtitle": "{}"
|
||||
}})#",
|
||||
w->m_iID, escapeJSONStrings(w->m_szName), escapeJSONStrings(PMONITOR ? PMONITOR->szName : "?"),
|
||||
escapeJSONStrings(PMONITOR ? std::to_string(PMONITOR->ID) : "null"), w->getWindows(), w->m_bHasFullscreenWindow ? "true" : "false",
|
||||
(uintptr_t)PLASTW.get(), PLASTW ? escapeJSONStrings(PLASTW->m_szTitle) : "", w->m_bPersistent ? "true" : "false");
|
||||
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\tispersistent: {}\n\n",
|
||||
w->m_iID, 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 : "", (int)w->m_bPersistent);
|
||||
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", w->getWindows(), (int)w->m_bHasFullscreenWindow,
|
||||
(uintptr_t)PLASTW.get(), PLASTW ? PLASTW->m_szTitle : "");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -479,11 +476,9 @@ static std::string layersRequest(eHyprCtlOutputFormat format, std::string reques
|
||||
"y": {},
|
||||
"w": {},
|
||||
"h": {},
|
||||
"namespace": "{}",
|
||||
"pid": {}
|
||||
"namespace": "{}"
|
||||
}},)#",
|
||||
(uintptr_t)layer.get(), layer->geometry.x, layer->geometry.y, layer->geometry.width, layer->geometry.height, escapeJSONStrings(layer->szNamespace),
|
||||
layer->getPID());
|
||||
(uintptr_t)layer.get(), layer->geometry.x, layer->geometry.y, layer->geometry.width, layer->geometry.height, escapeJSONStrings(layer->szNamespace));
|
||||
}
|
||||
|
||||
trimTrailingComma(result);
|
||||
@@ -514,8 +509,8 @@ static std::string layersRequest(eHyprCtlOutputFormat format, std::string reques
|
||||
result += std::format("\tLayer level {} ({}):\n", layerLevel, levelNames[layerLevel]);
|
||||
|
||||
for (auto const& layer : level) {
|
||||
result += std::format("\t\tLayer {:x}: xywh: {} {} {} {}, namespace: {}, pid: {}\n", (uintptr_t)layer.get(), layer->geometry.x, layer->geometry.y,
|
||||
layer->geometry.width, layer->geometry.height, layer->szNamespace, layer->getPID());
|
||||
result += std::format("\t\tLayer {:x}: xywh: {} {} {} {}, namespace: {}\n", (uintptr_t)layer.get(), layer->geometry.x, layer->geometry.y, layer->geometry.width,
|
||||
layer->geometry.height, layer->szNamespace);
|
||||
}
|
||||
|
||||
layerLevel++;
|
||||
@@ -813,11 +808,8 @@ static std::string globalShortcutsRequest(eHyprCtlOutputFormat format, std::stri
|
||||
std::string ret = "";
|
||||
const auto SHORTCUTS = PROTO::globalShortcuts->getAllShortcuts();
|
||||
if (format == eHyprCtlOutputFormat::FORMAT_NORMAL) {
|
||||
for (auto const& sh : SHORTCUTS) {
|
||||
for (auto const& sh : SHORTCUTS)
|
||||
ret += std::format("{}:{} -> {}\n", sh.appid, sh.id, sh.description);
|
||||
}
|
||||
if (ret.empty())
|
||||
ret = "none";
|
||||
} else {
|
||||
ret += "[";
|
||||
for (auto const& sh : SHORTCUTS) {
|
||||
@@ -1688,6 +1680,8 @@ CHyprCtl::CHyprCtl() {
|
||||
CHyprCtl::~CHyprCtl() {
|
||||
if (m_eventSource)
|
||||
wl_event_source_remove(m_eventSource);
|
||||
if (m_iSocketFD >= 0)
|
||||
close(m_iSocketFD);
|
||||
if (!m_socketPath.empty())
|
||||
unlink(m_socketPath.c_str());
|
||||
}
|
||||
@@ -1846,13 +1840,10 @@ static int hyprCtlFDTick(int fd, uint32_t mask, void* data) {
|
||||
if (mask & WL_EVENT_ERROR || mask & WL_EVENT_HANGUP)
|
||||
return 0;
|
||||
|
||||
if (!g_pHyprCtl->m_iSocketFD.isValid())
|
||||
return 0;
|
||||
|
||||
sockaddr_in clientAddress;
|
||||
socklen_t clientSize = sizeof(clientAddress);
|
||||
|
||||
const auto ACCEPTEDCONNECTION = accept4(g_pHyprCtl->m_iSocketFD.get(), (sockaddr*)&clientAddress, &clientSize, SOCK_CLOEXEC);
|
||||
const auto ACCEPTEDCONNECTION = accept4(g_pHyprCtl->m_iSocketFD, (sockaddr*)&clientAddress, &clientSize, SOCK_CLOEXEC);
|
||||
|
||||
std::array<char, 1024> readBuffer;
|
||||
|
||||
@@ -1909,9 +1900,9 @@ static int hyprCtlFDTick(int fd, uint32_t mask, void* data) {
|
||||
}
|
||||
|
||||
void CHyprCtl::startHyprCtlSocket() {
|
||||
m_iSocketFD = CFileDescriptor{socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0)};
|
||||
m_iSocketFD = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
|
||||
|
||||
if (!m_iSocketFD.isValid()) {
|
||||
if (m_iSocketFD < 0) {
|
||||
Debug::log(ERR, "Couldn't start the Hyprland Socket. (1) IPC will not work.");
|
||||
return;
|
||||
}
|
||||
@@ -1922,15 +1913,15 @@ void CHyprCtl::startHyprCtlSocket() {
|
||||
|
||||
strcpy(SERVERADDRESS.sun_path, m_socketPath.c_str());
|
||||
|
||||
if (bind(m_iSocketFD.get(), (sockaddr*)&SERVERADDRESS, SUN_LEN(&SERVERADDRESS)) < 0) {
|
||||
if (bind(m_iSocketFD, (sockaddr*)&SERVERADDRESS, SUN_LEN(&SERVERADDRESS)) < 0) {
|
||||
Debug::log(ERR, "Couldn't start the Hyprland Socket. (2) IPC will not work.");
|
||||
return;
|
||||
}
|
||||
|
||||
// 10 max queued.
|
||||
listen(m_iSocketFD.get(), 10);
|
||||
listen(m_iSocketFD, 10);
|
||||
|
||||
Debug::log(LOG, "Hypr socket started at {}", m_socketPath);
|
||||
|
||||
m_eventSource = wl_event_loop_add_fd(g_pCompositor->m_sWLEventLoop, m_iSocketFD.get(), WL_EVENT_READABLE, hyprCtlFDTick, nullptr);
|
||||
m_eventSource = wl_event_loop_add_fd(g_pCompositor->m_sWLEventLoop, m_iSocketFD, WL_EVENT_READABLE, hyprCtlFDTick, nullptr);
|
||||
}
|
||||
|
@@ -4,7 +4,6 @@
|
||||
#include "../helpers/MiscFunctions.hpp"
|
||||
#include "../desktop/Window.hpp"
|
||||
#include <functional>
|
||||
#include <hyprutils/os/FileDescriptor.hpp>
|
||||
|
||||
// exposed for main.cpp
|
||||
std::string systemInfoRequest(eHyprCtlOutputFormat format, std::string request);
|
||||
@@ -15,12 +14,12 @@ class CHyprCtl {
|
||||
CHyprCtl();
|
||||
~CHyprCtl();
|
||||
|
||||
std::string makeDynamicCall(const std::string& input);
|
||||
SP<SHyprCtlCommand> registerCommand(SHyprCtlCommand cmd);
|
||||
void unregisterCommand(const SP<SHyprCtlCommand>& cmd);
|
||||
std::string getReply(std::string);
|
||||
std::string makeDynamicCall(const std::string& input);
|
||||
SP<SHyprCtlCommand> registerCommand(SHyprCtlCommand cmd);
|
||||
void unregisterCommand(const SP<SHyprCtlCommand>& cmd);
|
||||
std::string getReply(std::string);
|
||||
|
||||
Hyprutils::OS::CFileDescriptor m_iSocketFD;
|
||||
int m_iSocketFD = -1;
|
||||
|
||||
struct {
|
||||
bool all = false;
|
||||
|
@@ -584,15 +584,3 @@ int CLayerSurface::popupsCount() {
|
||||
MONITORID CLayerSurface::monitorID() {
|
||||
return monitor ? monitor->ID : MONITOR_INVALID;
|
||||
}
|
||||
|
||||
pid_t CLayerSurface::getPID() {
|
||||
pid_t PID = -1;
|
||||
|
||||
if (!layerSurface || !layerSurface->surface || !layerSurface->surface->getResource() || !layerSurface->surface->getResource()->resource() ||
|
||||
!layerSurface->surface->getResource()->resource()->client)
|
||||
return -1;
|
||||
|
||||
wl_client_get_credentials(layerSurface->surface->getResource()->resource()->client, &PID, nullptr, nullptr);
|
||||
|
||||
return PID;
|
||||
}
|
||||
|
@@ -61,8 +61,6 @@ class CLayerSurface {
|
||||
std::string szNamespace = "";
|
||||
UP<CPopup> popupHead;
|
||||
|
||||
pid_t getPID();
|
||||
|
||||
void onDestroy();
|
||||
void onMap();
|
||||
void onUnmap();
|
||||
|
@@ -282,9 +282,6 @@ void CPopup::recheckTree() {
|
||||
}
|
||||
|
||||
void CPopup::recheckChildrenRecursive() {
|
||||
if (m_bInert || !m_pWLSurface)
|
||||
return;
|
||||
|
||||
std::vector<WP<CPopup>> cpy;
|
||||
std::ranges::for_each(m_vChildren, [&cpy](const auto& el) { cpy.emplace_back(el); });
|
||||
for (auto const& c : cpy) {
|
||||
@@ -350,19 +347,18 @@ WP<CPopup> CPopup::at(const Vector2D& globalCoords, bool allowsInput) {
|
||||
continue;
|
||||
|
||||
if (!allowsInput) {
|
||||
const bool HASSURFACE = p->m_pResource && p->m_pResource->surface;
|
||||
const Vector2D offset =
|
||||
p->m_pResource && p->m_pResource->surface ? (p->size() - p->m_pResource->geometry.size()) / 2.F - p->m_pResource->surface->current.geometry.pos() : Vector2D{};
|
||||
const Vector2D size = p->m_pResource ? p->m_pResource->geometry.size() : p->size();
|
||||
|
||||
Vector2D offset = HASSURFACE ? p->m_pResource->surface->current.geometry.pos() : Vector2D{};
|
||||
Vector2D size = HASSURFACE ? p->m_pResource->surface->current.geometry.size() : p->size();
|
||||
|
||||
if (size == Vector2D{})
|
||||
size = p->size();
|
||||
|
||||
const auto BOX = CBox{p->coordsGlobal() + offset, size};
|
||||
const auto BOX = CBox{p->coordsGlobal() + offset, size};
|
||||
if (BOX.containsPoint(globalCoords))
|
||||
return p;
|
||||
} else {
|
||||
const auto REGION = CRegion{p->m_pWLSurface->resource()->current.input}.intersect(CBox{{}, p->m_pWLSurface->resource()->current.size}).translate(p->coordsGlobal());
|
||||
const Vector2D offset =
|
||||
p->m_pResource && p->m_pResource->surface ? (p->size() - p->m_pResource->geometry.size()) / 2.F - p->m_pResource->surface->current.geometry.pos() : Vector2D{};
|
||||
const auto REGION =
|
||||
CRegion{p->m_pWLSurface->resource()->current.input}.intersect(CBox{{}, p->m_pWLSurface->resource()->current.size}).translate(p->coordsGlobal() + offset);
|
||||
if (REGION.containsPoint(globalCoords))
|
||||
return p;
|
||||
}
|
||||
@@ -370,7 +366,3 @@ WP<CPopup> CPopup::at(const Vector2D& globalCoords, bool allowsInput) {
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
bool CPopup::inert() const {
|
||||
return m_bInert;
|
||||
}
|
||||
|
@@ -34,7 +34,6 @@ class CPopup {
|
||||
void recheckTree();
|
||||
|
||||
bool visible();
|
||||
bool inert() const;
|
||||
|
||||
// will also loop over this node
|
||||
void breadthfirst(std::function<void(WP<CPopup>, void*)> fn, void* data);
|
||||
|
@@ -50,6 +50,10 @@ UP<CSubsurface> CSubsurface::create(SP<CWLSubsurfaceResource> pSubsurface, WP<CP
|
||||
return subsurface;
|
||||
}
|
||||
|
||||
CSubsurface::~CSubsurface() {
|
||||
;
|
||||
}
|
||||
|
||||
void CSubsurface::initSignals() {
|
||||
if (m_pSubsurface) {
|
||||
listeners.commitSubsurface = m_pSubsurface->surface->events.commit.registerListener([this](std::any d) { onCommit(); });
|
||||
@@ -107,7 +111,7 @@ void CSubsurface::onCommit() {
|
||||
|
||||
g_pHyprRenderer->damageSurface(m_pWLSurface->resource(), COORDS.x, COORDS.y);
|
||||
|
||||
if (m_pPopupParent && !m_pPopupParent->inert() && m_pPopupParent->m_pWLSurface)
|
||||
if (m_pPopupParent)
|
||||
m_pPopupParent->recheckTree();
|
||||
if (!m_pWindowParent.expired()) // I hate you firefox why are you doing this
|
||||
m_pWindowParent->m_pPopupHead->recheckTree();
|
||||
@@ -124,7 +128,7 @@ void CSubsurface::onCommit() {
|
||||
// g_pHyprRenderer->damageBox(box);
|
||||
|
||||
CBox box;
|
||||
if (m_pPopupParent && !m_pPopupParent->inert() && m_pPopupParent->m_pWLSurface)
|
||||
if (m_pPopupParent)
|
||||
box = m_pPopupParent->m_pWLSurface->getSurfaceBoxGlobal().value_or(CBox{});
|
||||
else if (m_pWindowParent)
|
||||
box = m_pWindowParent->getWindowMainSurfaceBox();
|
||||
|
@@ -17,7 +17,7 @@ class CSubsurface {
|
||||
static UP<CSubsurface> create(SP<CWLSubsurfaceResource> pSubsurface, PHLWINDOW pOwner);
|
||||
static UP<CSubsurface> create(SP<CWLSubsurfaceResource> pSubsurface, WP<CPopup> pOwner);
|
||||
|
||||
~CSubsurface() = default;
|
||||
~CSubsurface();
|
||||
|
||||
Vector2D coordsRelativeToParent();
|
||||
Vector2D coordsGlobal();
|
||||
@@ -64,4 +64,4 @@ class CSubsurface {
|
||||
void initSignals();
|
||||
void initExistingSubsurfaces(SP<CWLSurfaceResource> pSurface);
|
||||
void checkSiblingDamage();
|
||||
};
|
||||
};
|
@@ -98,7 +98,7 @@ CRegion CWLSurface::computeDamage() const {
|
||||
if (!m_pResource->current.texture)
|
||||
return {};
|
||||
|
||||
CRegion damage = m_pResource->current.accumulateBufferDamage();
|
||||
CRegion damage = m_pResource->accumulateCurrentBufferDamage();
|
||||
damage.transform(wlTransformToHyprutils(m_pResource->current.transform), m_pResource->current.bufferSize.x, m_pResource->current.bufferSize.y);
|
||||
|
||||
const auto BUFSIZE = m_pResource->current.bufferSize;
|
||||
|
@@ -13,10 +13,8 @@
|
||||
#include "../config/ConfigValue.hpp"
|
||||
#include "../managers/TokenManager.hpp"
|
||||
#include "../managers/AnimationManager.hpp"
|
||||
#include "../managers/ANRManager.hpp"
|
||||
#include "../protocols/XDGShell.hpp"
|
||||
#include "../protocols/core/Compositor.hpp"
|
||||
#include "../protocols/ContentType.hpp"
|
||||
#include "../xwayland/XWayland.hpp"
|
||||
#include "../helpers/Color.hpp"
|
||||
#include "../events/Events.hpp"
|
||||
@@ -31,7 +29,6 @@
|
||||
|
||||
using namespace Hyprutils::String;
|
||||
using namespace Hyprutils::Animation;
|
||||
using enum NContentType::eContentType;
|
||||
|
||||
PHLWINDOW CWindow::create(SP<CXWaylandSurface> surface) {
|
||||
PHLWINDOW pWindow = SP<CWindow>(new CWindow(surface));
|
||||
@@ -49,7 +46,6 @@ PHLWINDOW CWindow::create(SP<CXWaylandSurface> surface) {
|
||||
g_pAnimationManager->createAnimation(0.f, pWindow->m_fDimPercent, g_pConfigManager->getAnimationPropertyConfig("fadeDim"), pWindow, AVARDAMAGE_ENTIRE);
|
||||
g_pAnimationManager->createAnimation(0.f, pWindow->m_fMovingToWorkspaceAlpha, g_pConfigManager->getAnimationPropertyConfig("fadeOut"), pWindow, AVARDAMAGE_ENTIRE);
|
||||
g_pAnimationManager->createAnimation(0.f, pWindow->m_fMovingFromWorkspaceAlpha, g_pConfigManager->getAnimationPropertyConfig("fadeIn"), pWindow, AVARDAMAGE_ENTIRE);
|
||||
g_pAnimationManager->createAnimation(0.f, pWindow->m_notRespondingTint, g_pConfigManager->getAnimationPropertyConfig("fade"), pWindow, AVARDAMAGE_ENTIRE);
|
||||
|
||||
pWindow->addWindowDeco(makeUnique<CHyprDropShadowDecoration>(pWindow));
|
||||
pWindow->addWindowDeco(makeUnique<CHyprBorderDecoration>(pWindow));
|
||||
@@ -73,7 +69,6 @@ PHLWINDOW CWindow::create(SP<CXDGSurfaceResource> resource) {
|
||||
g_pAnimationManager->createAnimation(0.f, pWindow->m_fDimPercent, g_pConfigManager->getAnimationPropertyConfig("fadeDim"), pWindow, AVARDAMAGE_ENTIRE);
|
||||
g_pAnimationManager->createAnimation(0.f, pWindow->m_fMovingToWorkspaceAlpha, g_pConfigManager->getAnimationPropertyConfig("fadeOut"), pWindow, AVARDAMAGE_ENTIRE);
|
||||
g_pAnimationManager->createAnimation(0.f, pWindow->m_fMovingFromWorkspaceAlpha, g_pConfigManager->getAnimationPropertyConfig("fadeIn"), pWindow, AVARDAMAGE_ENTIRE);
|
||||
g_pAnimationManager->createAnimation(0.f, pWindow->m_notRespondingTint, g_pConfigManager->getAnimationPropertyConfig("fade"), pWindow, AVARDAMAGE_ENTIRE);
|
||||
|
||||
pWindow->addWindowDeco(makeUnique<CHyprDropShadowDecoration>(pWindow));
|
||||
pWindow->addWindowDeco(makeUnique<CHyprBorderDecoration>(pWindow));
|
||||
@@ -98,22 +93,22 @@ CWindow::CWindow(SP<CXDGSurfaceResource> resource) : m_pXDGSurface(resource) {
|
||||
CWindow::CWindow(SP<CXWaylandSurface> surface) : m_pXWaylandSurface(surface) {
|
||||
m_pWLSurface = CWLSurface::create();
|
||||
|
||||
listeners.map = m_pXWaylandSurface->events.map.registerListener([this](std::any d) { Events::listener_mapWindow(this, nullptr); });
|
||||
listeners.unmap = m_pXWaylandSurface->events.unmap.registerListener([this](std::any d) { Events::listener_unmapWindow(this, nullptr); });
|
||||
listeners.destroy = m_pXWaylandSurface->events.destroy.registerListener([this](std::any d) { Events::listener_destroyWindow(this, nullptr); });
|
||||
listeners.commit = m_pXWaylandSurface->events.commit.registerListener([this](std::any d) { Events::listener_commitWindow(this, nullptr); });
|
||||
listeners.configureRequest = m_pXWaylandSurface->events.configureRequest.registerListener([this](std::any d) { onX11ConfigureRequest(std::any_cast<CBox>(d)); });
|
||||
listeners.updateState = m_pXWaylandSurface->events.stateChanged.registerListener([this](std::any d) { onUpdateState(); });
|
||||
listeners.updateMetadata = m_pXWaylandSurface->events.metadataChanged.registerListener([this](std::any d) { onUpdateMeta(); });
|
||||
listeners.resourceChange = m_pXWaylandSurface->events.resourceChange.registerListener([this](std::any d) { onResourceChangeX11(); });
|
||||
listeners.activate = m_pXWaylandSurface->events.activate.registerListener([this](std::any d) { Events::listener_activateX11(this, nullptr); });
|
||||
listeners.map = m_pXWaylandSurface->events.map.registerListener([this](std::any d) { Events::listener_mapWindow(this, nullptr); });
|
||||
listeners.unmap = m_pXWaylandSurface->events.unmap.registerListener([this](std::any d) { Events::listener_unmapWindow(this, nullptr); });
|
||||
listeners.destroy = m_pXWaylandSurface->events.destroy.registerListener([this](std::any d) { Events::listener_destroyWindow(this, nullptr); });
|
||||
listeners.commit = m_pXWaylandSurface->events.commit.registerListener([this](std::any d) { Events::listener_commitWindow(this, nullptr); });
|
||||
listeners.configure = m_pXWaylandSurface->events.configure.registerListener([this](std::any d) { onX11Configure(std::any_cast<CBox>(d)); });
|
||||
listeners.updateState = m_pXWaylandSurface->events.stateChanged.registerListener([this](std::any d) { onUpdateState(); });
|
||||
listeners.updateMetadata = m_pXWaylandSurface->events.metadataChanged.registerListener([this](std::any d) { onUpdateMeta(); });
|
||||
listeners.resourceChange = m_pXWaylandSurface->events.resourceChange.registerListener([this](std::any d) { onResourceChangeX11(); });
|
||||
listeners.activate = m_pXWaylandSurface->events.activate.registerListener([this](std::any d) { Events::listener_activateX11(this, nullptr); });
|
||||
|
||||
if (m_pXWaylandSurface->overrideRedirect)
|
||||
listeners.setGeometry = m_pXWaylandSurface->events.setGeometry.registerListener([this](std::any d) { Events::listener_unmanagedSetGeometry(this, nullptr); });
|
||||
}
|
||||
|
||||
CWindow::~CWindow() {
|
||||
if (g_pCompositor->m_pLastWindow == m_pSelf) {
|
||||
if (g_pCompositor->m_pLastWindow.lock().get() == this) {
|
||||
g_pCompositor->m_pLastFocus.reset();
|
||||
g_pCompositor->m_pLastWindow.reset();
|
||||
}
|
||||
@@ -124,7 +119,7 @@ CWindow::~CWindow() {
|
||||
return;
|
||||
|
||||
g_pHyprRenderer->makeEGLCurrent();
|
||||
std::erase_if(g_pHyprOpenGL->m_mWindowFramebuffers, [&](const auto& other) { return other.first.expired() || other.first.get() == this; });
|
||||
std::erase_if(g_pHyprOpenGL->m_mWindowFramebuffers, [&](const auto& other) { return !other.first.lock() || other.first.lock().get() == this; });
|
||||
}
|
||||
|
||||
SBoxExtents CWindow::getFullWindowExtents() {
|
||||
@@ -415,7 +410,7 @@ void CWindow::moveToWorkspace(PHLWORKSPACE pWorkspace) {
|
||||
if (*PINITIALWSTRACKING == 2) {
|
||||
// persistent
|
||||
SInitialWorkspaceToken token = std::any_cast<SInitialWorkspaceToken>(TOKEN->data);
|
||||
if (token.primaryOwner == m_pSelf) {
|
||||
if (token.primaryOwner.lock().get() == this) {
|
||||
token.workspace = pWorkspace->getConfigName();
|
||||
TOKEN->data = token;
|
||||
}
|
||||
@@ -455,12 +450,13 @@ void CWindow::moveToWorkspace(PHLWORKSPACE pWorkspace) {
|
||||
}
|
||||
|
||||
if (const auto SWALLOWED = m_pSwallowed.lock()) {
|
||||
if (SWALLOWED->m_bCurrentlySwallowed) {
|
||||
SWALLOWED->moveToWorkspace(pWorkspace);
|
||||
SWALLOWED->m_pMonitor = m_pMonitor;
|
||||
}
|
||||
SWALLOWED->moveToWorkspace(pWorkspace);
|
||||
SWALLOWED->m_pMonitor = m_pMonitor;
|
||||
}
|
||||
|
||||
// update xwayland coords
|
||||
sendWindowSize(m_vRealSize->goal());
|
||||
|
||||
if (OLDWORKSPACE && g_pCompositor->isWorkspaceSpecial(OLDWORKSPACE->m_iID) && OLDWORKSPACE->getWindows() == 0 && *PCLOSEONLASTSPECIAL) {
|
||||
if (const auto PMONITOR = OLDWORKSPACE->m_pMonitor.lock(); PMONITOR)
|
||||
PMONITOR->setSpecialWorkspace(nullptr);
|
||||
@@ -505,7 +501,7 @@ void CWindow::onUnmap() {
|
||||
if (*PINITIALWSTRACKING == 2) {
|
||||
// persistent token, but the first window got removed so the token is gone
|
||||
SInitialWorkspaceToken token = std::any_cast<SInitialWorkspaceToken>(TOKEN->data);
|
||||
if (token.primaryOwner == m_pSelf)
|
||||
if (token.primaryOwner.lock().get() == this)
|
||||
g_pTokenManager->removeToken(TOKEN);
|
||||
}
|
||||
}
|
||||
@@ -513,7 +509,7 @@ void CWindow::onUnmap() {
|
||||
|
||||
m_iLastWorkspace = m_pWorkspace->m_iID;
|
||||
|
||||
std::erase_if(g_pCompositor->m_vWindowFocusHistory, [this](const auto& other) { return other.expired() || other == m_pSelf; });
|
||||
std::erase_if(g_pCompositor->m_vWindowFocusHistory, [&](const auto& other) { return other.expired() || other.lock().get() == this; });
|
||||
|
||||
if (*PCLOSEONLASTSPECIAL && m_pWorkspace && m_pWorkspace->getWindows() == 0 && onSpecialWorkspace()) {
|
||||
const auto PMONITOR = m_pMonitor.lock();
|
||||
@@ -523,7 +519,7 @@ void CWindow::onUnmap() {
|
||||
|
||||
const auto PMONITOR = m_pMonitor.lock();
|
||||
|
||||
if (PMONITOR && PMONITOR->solitaryClient == m_pSelf)
|
||||
if (PMONITOR && PMONITOR->solitaryClient.lock().get() == this)
|
||||
PMONITOR->solitaryClient.reset();
|
||||
|
||||
if (m_pWorkspace) {
|
||||
@@ -563,15 +559,6 @@ void CWindow::onMap() {
|
||||
*m_fBorderAngleAnimationProgress = 1.f;
|
||||
}
|
||||
|
||||
m_vRealSize->setCallbackOnBegin(
|
||||
[this](auto) {
|
||||
if (!m_bIsMapped || isX11OverrideRedirect())
|
||||
return;
|
||||
|
||||
sendWindowSize();
|
||||
},
|
||||
false);
|
||||
|
||||
m_fMovingFromWorkspaceAlpha->setValueAndWarp(1.F);
|
||||
|
||||
g_pCompositor->m_vWindowFocusHistory.push_back(m_pSelf);
|
||||
@@ -609,8 +596,9 @@ void CWindow::onBorderAngleAnimEnd(WP<CBaseAnimatedVariable> pav) {
|
||||
void CWindow::setHidden(bool hidden) {
|
||||
m_bHidden = hidden;
|
||||
|
||||
if (hidden && g_pCompositor->m_pLastWindow == m_pSelf)
|
||||
if (hidden && g_pCompositor->m_pLastWindow.lock().get() == this) {
|
||||
g_pCompositor->m_pLastWindow.reset();
|
||||
}
|
||||
|
||||
setSuspended(hidden);
|
||||
}
|
||||
@@ -776,25 +764,21 @@ void CWindow::applyDynamicRule(const SP<CWindowRule>& r) {
|
||||
}
|
||||
case CWindowRule::RULE_PROP: {
|
||||
const CVarList VARS(r->szRule, 0, ' ');
|
||||
if (auto search = NWindowProperties::intWindowProperties.find(VARS[1]); search != NWindowProperties::intWindowProperties.end()) {
|
||||
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 = NWindowProperties::floatWindowProperties.find(VARS[1]); search != NWindowProperties::floatWindowProperties.end()) {
|
||||
} 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 = NWindowProperties::boolWindowProperties.find(VARS[1]); search != NWindowProperties::boolWindowProperties.end()) {
|
||||
} else if (auto search = g_pConfigManager->mbWindowProperties.find(VARS[1]); search != g_pConfigManager->mbWindowProperties.end()) {
|
||||
try {
|
||||
*(search->second(m_pSelf.lock())) = CWindowOverridableVar(VARS[2].empty() ? true : (bool)std::stoi(VARS[2]), priority);
|
||||
} catch (std::exception& e) { Debug::log(ERR, "Rule \"{}\" failed with: {}", r->szRule, e.what()); }
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CWindowRule::RULE_PERSISTENTSIZE: {
|
||||
m_sWindowData.persistentSize = CWindowOverridableVar(true, PRIORITY_WINDOW_RULE);
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
@@ -904,7 +888,7 @@ void CWindow::createGroup() {
|
||||
}
|
||||
|
||||
void CWindow::destroyGroup() {
|
||||
if (m_sGroupData.pNextWindow == m_pSelf) {
|
||||
if (m_sGroupData.pNextWindow.lock().get() == this) {
|
||||
if (m_eGroupRules & GROUP_SET_ALWAYS) {
|
||||
Debug::log(LOG, "destoryGroup: window:{:x},title:{} has rule [group set always], ignored", (uintptr_t)this, this->m_szTitle);
|
||||
return;
|
||||
@@ -986,7 +970,7 @@ PHLWINDOW CWindow::getGroupCurrent() {
|
||||
int CWindow::getGroupSize() {
|
||||
int size = 1;
|
||||
PHLWINDOW curr = m_pSelf.lock();
|
||||
while (curr->m_sGroupData.pNextWindow != m_pSelf) {
|
||||
while (curr->m_sGroupData.pNextWindow.lock().get() != this) {
|
||||
curr = curr->m_sGroupData.pNextWindow.lock();
|
||||
size++;
|
||||
}
|
||||
@@ -1092,7 +1076,7 @@ void CWindow::insertWindowToGroup(PHLWINDOW pWindow) {
|
||||
PHLWINDOW CWindow::getGroupPrevious() {
|
||||
PHLWINDOW curr = m_sGroupData.pNextWindow.lock();
|
||||
|
||||
while (curr != m_pSelf && curr->m_sGroupData.pNextWindow != m_pSelf)
|
||||
while (curr != m_pSelf.lock() && curr->m_sGroupData.pNextWindow.lock().get() != this)
|
||||
curr = curr->m_sGroupData.pNextWindow.lock();
|
||||
|
||||
return curr;
|
||||
@@ -1107,7 +1091,7 @@ void CWindow::switchWithWindowInGroup(PHLWINDOW pWindow) {
|
||||
m_sGroupData.pNextWindow = pWindow->m_sGroupData.pNextWindow;
|
||||
pWindow->m_sGroupData.pNextWindow = m_pSelf;
|
||||
|
||||
} else if (pWindow->m_sGroupData.pNextWindow == m_pSelf) { // A -> pWindow -> this -> B >> A -> this -> pWindow -> B
|
||||
} else if (pWindow->m_sGroupData.pNextWindow.lock().get() == this) { // A -> pWindow -> this -> B >> A -> this -> pWindow -> B
|
||||
pWindow->getGroupPrevious()->m_sGroupData.pNextWindow = m_pSelf;
|
||||
pWindow->m_sGroupData.pNextWindow = m_sGroupData.pNextWindow;
|
||||
m_sGroupData.pNextWindow = pWindow;
|
||||
@@ -1258,7 +1242,7 @@ void CWindow::setAnimationsToMove() {
|
||||
|
||||
void CWindow::onWorkspaceAnimUpdate() {
|
||||
// clip box for animated offsets
|
||||
if (!m_bIsFloating || m_bPinned || isFullscreen() || m_bDraggingTiled) {
|
||||
if (!m_bIsFloating || m_bPinned || isFullscreen()) {
|
||||
m_vFloatingOffset = Vector2D(0, 0);
|
||||
return;
|
||||
}
|
||||
@@ -1327,6 +1311,7 @@ void CWindow::clampWindowSize(const std::optional<Vector2D> minSize, const std::
|
||||
|
||||
*m_vRealPosition = m_vRealPosition->goal() + DELTA / 2.0;
|
||||
*m_vRealSize = NEWSIZE;
|
||||
sendWindowSize(NEWSIZE);
|
||||
}
|
||||
|
||||
bool CWindow::isFullscreen() {
|
||||
@@ -1536,21 +1521,21 @@ void CWindow::onResourceChangeX11() {
|
||||
Debug::log(LOG, "xwayland window {:x} -> association to {:x}", (uintptr_t)m_pXWaylandSurface.get(), (uintptr_t)m_pWLSurface->resource().get());
|
||||
}
|
||||
|
||||
void CWindow::onX11ConfigureRequest(CBox box) {
|
||||
void CWindow::onX11Configure(CBox box) {
|
||||
|
||||
if (!m_pXWaylandSurface->surface || !m_pXWaylandSurface->mapped || !m_bIsMapped) {
|
||||
m_pXWaylandSurface->configure(box);
|
||||
m_vPendingReportedSize = box.size();
|
||||
m_vReportedSize = box.size();
|
||||
m_vReportedPosition = box.pos();
|
||||
updateX11SurfaceScale();
|
||||
if (const auto PMONITOR = m_pMonitor.lock(); PMONITOR)
|
||||
m_fX11SurfaceScaledBy = PMONITOR->scale;
|
||||
return;
|
||||
}
|
||||
|
||||
g_pHyprRenderer->damageWindow(m_pSelf.lock());
|
||||
|
||||
if (!m_bIsFloating || isFullscreen() || g_pInputManager->currentlyDraggedWindow == m_pSelf) {
|
||||
sendWindowSize(true);
|
||||
sendWindowSize(m_vRealSize->goal(), true);
|
||||
g_pInputManager->refocus();
|
||||
g_pHyprRenderer->damageWindow(m_pSelf.lock());
|
||||
return;
|
||||
@@ -1561,20 +1546,27 @@ void CWindow::onX11ConfigureRequest(CBox box) {
|
||||
else
|
||||
setHidden(true);
|
||||
|
||||
m_vRealPosition->setValueAndWarp(xwaylandPositionToReal(box.pos()));
|
||||
m_vRealSize->setValueAndWarp(xwaylandSizeToReal(box.size()));
|
||||
const auto LOGICALPOS = g_pXWaylandManager->xwaylandToWaylandCoords(box.pos());
|
||||
|
||||
m_vRealPosition->setValueAndWarp(LOGICALPOS);
|
||||
m_vRealSize->setValueAndWarp(box.size());
|
||||
|
||||
static auto PXWLFORCESCALEZERO = CConfigValue<Hyprlang::INT>("xwayland:force_zero_scaling");
|
||||
if (*PXWLFORCESCALEZERO) {
|
||||
if (const auto PMONITOR = m_pMonitor.lock(); PMONITOR) {
|
||||
m_vRealSize->setValueAndWarp(m_vRealSize->goal() / PMONITOR->scale);
|
||||
m_fX11SurfaceScaledBy = PMONITOR->scale;
|
||||
}
|
||||
}
|
||||
|
||||
m_vPosition = m_vRealPosition->goal();
|
||||
m_vSize = m_vRealSize->goal();
|
||||
|
||||
if (m_vPendingReportedSize != box.size() || m_vReportedPosition != box.pos()) {
|
||||
m_pXWaylandSurface->configure(box);
|
||||
m_vReportedSize = box.size();
|
||||
m_vPendingReportedSize = box.size();
|
||||
m_vReportedPosition = box.pos();
|
||||
}
|
||||
sendWindowSize(box.size(), true);
|
||||
|
||||
m_vPendingReportedSize = box.size();
|
||||
m_vReportedSize = box.size();
|
||||
|
||||
updateX11SurfaceScale();
|
||||
updateWindowDecos();
|
||||
|
||||
if (!m_pWorkspace || !m_pWorkspace->isVisible())
|
||||
@@ -1630,17 +1622,17 @@ PHLWINDOW CWindow::getSwallower() {
|
||||
if (!(*PSWALLOWREGEX).empty())
|
||||
std::erase_if(candidates, [&](const auto& other) { return !RE2::FullMatch(other->m_szClass, *PSWALLOWREGEX); });
|
||||
|
||||
if (candidates.size() == 0)
|
||||
if (candidates.size() <= 0)
|
||||
return nullptr;
|
||||
|
||||
if (!(*PSWALLOWEXREGEX).empty())
|
||||
std::erase_if(candidates, [&](const auto& other) { return RE2::FullMatch(other->m_szTitle, *PSWALLOWEXREGEX); });
|
||||
|
||||
if (candidates.size() == 0)
|
||||
if (candidates.size() <= 0)
|
||||
return nullptr;
|
||||
|
||||
if (candidates.size() == 1)
|
||||
return candidates[0];
|
||||
return candidates.at(0);
|
||||
|
||||
// walk up the focus history and find the last focused
|
||||
for (auto const& w : g_pCompositor->m_vWindowFocusHistory) {
|
||||
@@ -1652,17 +1644,17 @@ PHLWINDOW CWindow::getSwallower() {
|
||||
}
|
||||
|
||||
// if none are found (??) then just return the first one
|
||||
return candidates[0];
|
||||
return candidates.at(0);
|
||||
}
|
||||
|
||||
void CWindow::unsetWindowData(eOverridePriority priority) {
|
||||
for (auto const& element : NWindowProperties::boolWindowProperties) {
|
||||
for (auto const& element : g_pConfigManager->mbWindowProperties) {
|
||||
element.second(m_pSelf.lock())->unset(priority);
|
||||
}
|
||||
for (auto const& element : NWindowProperties::intWindowProperties) {
|
||||
for (auto const& element : g_pConfigManager->miWindowProperties) {
|
||||
element.second(m_pSelf.lock())->unset(priority);
|
||||
}
|
||||
for (auto const& element : NWindowProperties::floatWindowProperties) {
|
||||
for (auto const& element : g_pConfigManager->mfWindowProperties) {
|
||||
element.second(m_pSelf.lock())->unset(priority);
|
||||
}
|
||||
}
|
||||
@@ -1701,108 +1693,34 @@ Vector2D CWindow::requestedMaxSize() {
|
||||
return maxSize;
|
||||
}
|
||||
|
||||
Vector2D CWindow::realToReportSize() {
|
||||
if (!m_bIsX11)
|
||||
return m_vRealSize->goal().clamp(Vector2D{0, 0}, Vector2D{std::numeric_limits<double>::infinity(), std::numeric_limits<double>::infinity()});
|
||||
|
||||
void CWindow::sendWindowSize(Vector2D size, bool force, std::optional<Vector2D> overridePos) {
|
||||
static auto PXWLFORCESCALEZERO = CConfigValue<Hyprlang::INT>("xwayland:force_zero_scaling");
|
||||
const auto PMONITOR = m_pMonitor.lock();
|
||||
|
||||
const auto REPORTSIZE = m_vRealSize->goal().clamp(Vector2D{1, 1}, Vector2D{std::numeric_limits<double>::infinity(), std::numeric_limits<double>::infinity()});
|
||||
const auto PMONITOR = m_pMonitor.lock();
|
||||
|
||||
if (*PXWLFORCESCALEZERO && PMONITOR)
|
||||
return REPORTSIZE * PMONITOR->scale;
|
||||
|
||||
return REPORTSIZE;
|
||||
}
|
||||
|
||||
Vector2D CWindow::realToReportPosition() {
|
||||
if (!m_bIsX11)
|
||||
return m_vRealPosition->goal();
|
||||
|
||||
return g_pXWaylandManager->waylandToXWaylandCoords(m_vRealPosition->goal());
|
||||
}
|
||||
|
||||
Vector2D CWindow::xwaylandSizeToReal(Vector2D size) {
|
||||
static auto PXWLFORCESCALEZERO = CConfigValue<Hyprlang::INT>("xwayland:force_zero_scaling");
|
||||
|
||||
const auto PMONITOR = m_pMonitor.lock();
|
||||
const auto SIZE = size.clamp(Vector2D{1, 1}, Vector2D{std::numeric_limits<double>::infinity(), std::numeric_limits<double>::infinity()});
|
||||
const auto SCALE = *PXWLFORCESCALEZERO ? PMONITOR->scale : 1.0f;
|
||||
|
||||
return SIZE / SCALE;
|
||||
}
|
||||
|
||||
Vector2D CWindow::xwaylandPositionToReal(Vector2D pos) {
|
||||
return g_pXWaylandManager->xwaylandToWaylandCoords(pos);
|
||||
}
|
||||
|
||||
void CWindow::updateX11SurfaceScale() {
|
||||
static auto PXWLFORCESCALEZERO = CConfigValue<Hyprlang::INT>("xwayland:force_zero_scaling");
|
||||
|
||||
m_fX11SurfaceScaledBy = 1.0f;
|
||||
if (m_bIsX11 && *PXWLFORCESCALEZERO) {
|
||||
if (const auto PMONITOR = m_pMonitor.lock(); PMONITOR)
|
||||
m_fX11SurfaceScaledBy = PMONITOR->scale;
|
||||
}
|
||||
}
|
||||
|
||||
void CWindow::sendWindowSize(bool force) {
|
||||
const auto PMONITOR = m_pMonitor.lock();
|
||||
|
||||
Debug::log(TRACE, "sendWindowSize: window:{:x},title:{} with real pos {}, real size {} (force: {})", (uintptr_t)this, this->m_szTitle, m_vRealPosition->goal(),
|
||||
m_vRealSize->goal(), force);
|
||||
size = size.clamp(Vector2D{1, 1}, Vector2D{std::numeric_limits<double>::infinity(), std::numeric_limits<double>::infinity()});
|
||||
|
||||
// calculate pos
|
||||
// TODO: this should be decoupled from setWindowSize IMO
|
||||
const auto REPORTPOS = realToReportPosition();
|
||||
Vector2D windowPos = overridePos.value_or(m_vRealPosition->goal());
|
||||
|
||||
const auto REPORTSIZE = realToReportSize();
|
||||
if (m_bIsX11 && PMONITOR) {
|
||||
windowPos = g_pXWaylandManager->waylandToXWaylandCoords(windowPos);
|
||||
if (*PXWLFORCESCALEZERO)
|
||||
size *= PMONITOR->scale;
|
||||
}
|
||||
|
||||
if (!force && m_vPendingReportedSize == REPORTSIZE && (m_vReportedPosition == REPORTPOS || !m_bIsX11))
|
||||
if (!force && m_vPendingReportedSize == size && (windowPos == m_vReportedPosition || !m_bIsX11))
|
||||
return;
|
||||
|
||||
m_vReportedPosition = REPORTPOS;
|
||||
m_vPendingReportedSize = REPORTSIZE;
|
||||
updateX11SurfaceScale();
|
||||
m_vReportedPosition = windowPos;
|
||||
m_vPendingReportedSize = size;
|
||||
m_fX11SurfaceScaledBy = 1.0f;
|
||||
|
||||
if (*PXWLFORCESCALEZERO && m_bIsX11 && PMONITOR)
|
||||
m_fX11SurfaceScaledBy = PMONITOR->scale;
|
||||
|
||||
if (m_bIsX11 && m_pXWaylandSurface)
|
||||
m_pXWaylandSurface->configure({REPORTPOS, REPORTSIZE});
|
||||
m_pXWaylandSurface->configure({windowPos, size});
|
||||
else if (m_pXDGSurface && m_pXDGSurface->toplevel)
|
||||
m_vPendingSizeAcks.emplace_back(m_pXDGSurface->toplevel->setSize(REPORTSIZE), REPORTPOS.floor());
|
||||
}
|
||||
|
||||
NContentType::eContentType CWindow::getContentType() {
|
||||
if (!m_pWLSurface || !m_pWLSurface->resource() || !m_pWLSurface->resource()->contentType.valid())
|
||||
return CONTENT_TYPE_NONE;
|
||||
|
||||
return m_pWLSurface->resource()->contentType->value;
|
||||
}
|
||||
|
||||
void CWindow::setContentType(NContentType::eContentType contentType) {
|
||||
if (!m_pWLSurface->resource()->contentType.valid())
|
||||
m_pWLSurface->resource()->contentType = PROTO::contentType->getContentType(m_pWLSurface->resource());
|
||||
// else disallow content type change if proto is used?
|
||||
|
||||
Debug::log(INFO, "ContentType for window {}", (int)contentType);
|
||||
m_pWLSurface->resource()->contentType->value = contentType;
|
||||
}
|
||||
|
||||
void CWindow::deactivateGroupMembers() {
|
||||
auto curr = getGroupHead();
|
||||
while (curr) {
|
||||
if (curr != m_pSelf.lock()) {
|
||||
if (curr->m_bIsX11)
|
||||
curr->m_pXWaylandSurface->activate(false);
|
||||
else if (curr->m_pXDGSurface && curr->m_pXDGSurface->toplevel)
|
||||
curr->m_pXDGSurface->toplevel->setActive(false);
|
||||
}
|
||||
|
||||
curr = curr->m_sGroupData.pNextWindow.lock();
|
||||
if (curr == getGroupHead())
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool CWindow::isNotResponding() {
|
||||
return g_pANRManager->isNotResponding(m_pSelf.lock());
|
||||
m_vPendingSizeAcks.emplace_back(m_pXDGSurface->toplevel->setSize(size), size.floor());
|
||||
}
|
||||
|
@@ -19,7 +19,6 @@
|
||||
#include "WLSurface.hpp"
|
||||
#include "Workspace.hpp"
|
||||
#include "WindowRule.hpp"
|
||||
#include "../protocols/types/ContentType.hpp"
|
||||
|
||||
class CXDGSurfaceResource;
|
||||
class CXWaylandSurface;
|
||||
@@ -198,8 +197,6 @@ struct SWindowData {
|
||||
|
||||
CWindowOverridableVar<CGradientValueData> activeBorderColor;
|
||||
CWindowOverridableVar<CGradientValueData> inactiveBorderColor;
|
||||
|
||||
CWindowOverridableVar<bool> persistentSize;
|
||||
};
|
||||
|
||||
struct SInitialWorkspaceToken {
|
||||
@@ -357,8 +354,7 @@ class CWindow {
|
||||
|
||||
// swallowing
|
||||
PHLWINDOWREF m_pSwallowed;
|
||||
bool m_bCurrentlySwallowed = false;
|
||||
bool m_bGroupSwallowed = false;
|
||||
bool m_bGroupSwallowed = false;
|
||||
|
||||
// focus stuff
|
||||
bool m_bStayFocused = false;
|
||||
@@ -390,9 +386,6 @@ class CWindow {
|
||||
// window tags
|
||||
CTagKeeper m_tags;
|
||||
|
||||
// ANR
|
||||
PHLANIMVAR<float> m_notRespondingTint;
|
||||
|
||||
// For the list lookup
|
||||
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 &&
|
||||
@@ -400,94 +393,85 @@ class CWindow {
|
||||
}
|
||||
|
||||
// methods
|
||||
CBox getFullWindowBoundingBox();
|
||||
SBoxExtents getFullWindowExtents();
|
||||
CBox getWindowBoxUnified(uint64_t props);
|
||||
CBox getWindowIdealBoundingBoxIgnoreReserved();
|
||||
void addWindowDeco(UP<IHyprWindowDecoration> deco);
|
||||
void updateWindowDecos();
|
||||
void removeWindowDeco(IHyprWindowDecoration* deco);
|
||||
void uncacheWindowDecos();
|
||||
bool checkInputOnDecos(const eInputType, const Vector2D&, std::any = {});
|
||||
pid_t getPID();
|
||||
IHyprWindowDecoration* getDecorationByType(eDecorationType);
|
||||
void updateToplevel();
|
||||
void updateSurfaceScaleTransformDetails(bool force = false);
|
||||
void moveToWorkspace(PHLWORKSPACE);
|
||||
PHLWINDOW x11TransientFor();
|
||||
void onUnmap();
|
||||
void onMap();
|
||||
void setHidden(bool hidden);
|
||||
bool isHidden();
|
||||
void applyDynamicRule(const SP<CWindowRule>& r);
|
||||
void updateDynamicRules();
|
||||
SBoxExtents getFullWindowReservedArea();
|
||||
Vector2D middle();
|
||||
bool opaque();
|
||||
float rounding();
|
||||
float roundingPower();
|
||||
bool canBeTorn();
|
||||
void setSuspended(bool suspend);
|
||||
bool visibleOnMonitor(PHLMONITOR pMonitor);
|
||||
WORKSPACEID workspaceID();
|
||||
MONITORID monitorID();
|
||||
bool onSpecialWorkspace();
|
||||
void activate(bool force = false);
|
||||
int surfacesCount();
|
||||
void clampWindowSize(const std::optional<Vector2D> minSize, const std::optional<Vector2D> maxSize);
|
||||
bool isFullscreen();
|
||||
bool isEffectiveInternalFSMode(const eFullscreenMode);
|
||||
int getRealBorderSize();
|
||||
float getScrollMouse();
|
||||
float getScrollTouchpad();
|
||||
void updateWindowData();
|
||||
void updateWindowData(const struct SWorkspaceRule&);
|
||||
void onBorderAngleAnimEnd(WP<Hyprutils::Animation::CBaseAnimatedVariable> pav);
|
||||
bool isInCurvedCorner(double x, double y);
|
||||
bool hasPopupAt(const Vector2D& pos);
|
||||
int popupsCount();
|
||||
void applyGroupRules();
|
||||
void createGroup();
|
||||
void destroyGroup();
|
||||
PHLWINDOW getGroupHead();
|
||||
PHLWINDOW getGroupTail();
|
||||
PHLWINDOW getGroupCurrent();
|
||||
PHLWINDOW getGroupPrevious();
|
||||
PHLWINDOW getGroupWindowByIndex(int);
|
||||
int getGroupSize();
|
||||
bool canBeGroupedInto(PHLWINDOW pWindow);
|
||||
void setGroupCurrent(PHLWINDOW pWindow);
|
||||
void insertWindowToGroup(PHLWINDOW pWindow);
|
||||
void updateGroupOutputs();
|
||||
void switchWithWindowInGroup(PHLWINDOW pWindow);
|
||||
void setAnimationsToMove();
|
||||
void onWorkspaceAnimUpdate();
|
||||
void onFocusAnimUpdate();
|
||||
void onUpdateState();
|
||||
void onUpdateMeta();
|
||||
void onX11ConfigureRequest(CBox box);
|
||||
void onResourceChangeX11();
|
||||
std::string fetchTitle();
|
||||
std::string fetchClass();
|
||||
void warpCursor(bool force = false);
|
||||
PHLWINDOW getSwallower();
|
||||
void unsetWindowData(eOverridePriority priority);
|
||||
bool isX11OverrideRedirect();
|
||||
bool isModal();
|
||||
Vector2D requestedMinSize();
|
||||
Vector2D requestedMaxSize();
|
||||
Vector2D realToReportSize();
|
||||
Vector2D realToReportPosition();
|
||||
Vector2D xwaylandSizeToReal(Vector2D size);
|
||||
Vector2D xwaylandPositionToReal(Vector2D size);
|
||||
void updateX11SurfaceScale();
|
||||
void sendWindowSize(bool force = false);
|
||||
NContentType::eContentType getContentType();
|
||||
void setContentType(NContentType::eContentType contentType);
|
||||
void deactivateGroupMembers();
|
||||
bool isNotResponding();
|
||||
CBox getFullWindowBoundingBox();
|
||||
SBoxExtents getFullWindowExtents();
|
||||
CBox getWindowBoxUnified(uint64_t props);
|
||||
CBox getWindowIdealBoundingBoxIgnoreReserved();
|
||||
void addWindowDeco(UP<IHyprWindowDecoration> deco);
|
||||
void updateWindowDecos();
|
||||
void removeWindowDeco(IHyprWindowDecoration* deco);
|
||||
void uncacheWindowDecos();
|
||||
bool checkInputOnDecos(const eInputType, const Vector2D&, std::any = {});
|
||||
pid_t getPID();
|
||||
IHyprWindowDecoration* getDecorationByType(eDecorationType);
|
||||
void updateToplevel();
|
||||
void updateSurfaceScaleTransformDetails(bool force = false);
|
||||
void moveToWorkspace(PHLWORKSPACE);
|
||||
PHLWINDOW x11TransientFor();
|
||||
void onUnmap();
|
||||
void onMap();
|
||||
void setHidden(bool hidden);
|
||||
bool isHidden();
|
||||
void applyDynamicRule(const SP<CWindowRule>& r);
|
||||
void updateDynamicRules();
|
||||
SBoxExtents getFullWindowReservedArea();
|
||||
Vector2D middle();
|
||||
bool opaque();
|
||||
float rounding();
|
||||
float roundingPower();
|
||||
bool canBeTorn();
|
||||
void setSuspended(bool suspend);
|
||||
bool visibleOnMonitor(PHLMONITOR pMonitor);
|
||||
WORKSPACEID workspaceID();
|
||||
MONITORID monitorID();
|
||||
bool onSpecialWorkspace();
|
||||
void activate(bool force = false);
|
||||
int surfacesCount();
|
||||
void clampWindowSize(const std::optional<Vector2D> minSize, const std::optional<Vector2D> maxSize);
|
||||
bool isFullscreen();
|
||||
bool isEffectiveInternalFSMode(const eFullscreenMode);
|
||||
int getRealBorderSize();
|
||||
float getScrollMouse();
|
||||
float getScrollTouchpad();
|
||||
void updateWindowData();
|
||||
void updateWindowData(const struct SWorkspaceRule&);
|
||||
void onBorderAngleAnimEnd(WP<Hyprutils::Animation::CBaseAnimatedVariable> pav);
|
||||
bool isInCurvedCorner(double x, double y);
|
||||
bool hasPopupAt(const Vector2D& pos);
|
||||
int popupsCount();
|
||||
void applyGroupRules();
|
||||
void createGroup();
|
||||
void destroyGroup();
|
||||
PHLWINDOW getGroupHead();
|
||||
PHLWINDOW getGroupTail();
|
||||
PHLWINDOW getGroupCurrent();
|
||||
PHLWINDOW getGroupPrevious();
|
||||
PHLWINDOW getGroupWindowByIndex(int);
|
||||
int getGroupSize();
|
||||
bool canBeGroupedInto(PHLWINDOW pWindow);
|
||||
void setGroupCurrent(PHLWINDOW pWindow);
|
||||
void insertWindowToGroup(PHLWINDOW pWindow);
|
||||
void updateGroupOutputs();
|
||||
void switchWithWindowInGroup(PHLWINDOW pWindow);
|
||||
void setAnimationsToMove();
|
||||
void onWorkspaceAnimUpdate();
|
||||
void onFocusAnimUpdate();
|
||||
void onUpdateState();
|
||||
void onUpdateMeta();
|
||||
void onX11Configure(CBox box);
|
||||
void onResourceChangeX11();
|
||||
std::string fetchTitle();
|
||||
std::string fetchClass();
|
||||
void warpCursor(bool force = false);
|
||||
PHLWINDOW getSwallower();
|
||||
void unsetWindowData(eOverridePriority priority);
|
||||
bool isX11OverrideRedirect();
|
||||
bool isModal();
|
||||
Vector2D requestedMinSize();
|
||||
Vector2D requestedMaxSize();
|
||||
void sendWindowSize(Vector2D size, bool force = false, std::optional<Vector2D> overridePos = std::nullopt);
|
||||
|
||||
CBox getWindowMainSurfaceBox() const {
|
||||
CBox getWindowMainSurfaceBox() const {
|
||||
return {m_vRealPosition->value().x, m_vRealPosition->value().y, m_vRealSize->value().x, m_vRealSize->value().y};
|
||||
}
|
||||
|
||||
@@ -508,7 +492,7 @@ class CWindow {
|
||||
CHyprSignalListener commit;
|
||||
CHyprSignalListener destroy;
|
||||
CHyprSignalListener activate;
|
||||
CHyprSignalListener configureRequest;
|
||||
CHyprSignalListener configure;
|
||||
CHyprSignalListener setGeometry;
|
||||
CHyprSignalListener updateState;
|
||||
CHyprSignalListener updateMetadata;
|
||||
@@ -542,42 +526,6 @@ inline bool validMapped(PHLWINDOWREF w) {
|
||||
return w->m_bIsMapped;
|
||||
}
|
||||
|
||||
namespace NWindowProperties {
|
||||
static const std::unordered_map<std::string, std::function<CWindowOverridableVar<bool>*(const PHLWINDOW&)>> boolWindowProperties = {
|
||||
{"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; }},
|
||||
};
|
||||
|
||||
const std::unordered_map<std::string, std::function<CWindowOverridableVar<int>*(const PHLWINDOW&)>> intWindowProperties = {
|
||||
{"rounding", [](const PHLWINDOW& pWindow) { return &pWindow->m_sWindowData.rounding; }},
|
||||
{"bordersize", [](const PHLWINDOW& pWindow) { return &pWindow->m_sWindowData.borderSize; }},
|
||||
};
|
||||
|
||||
const std::unordered_map<std::string, std::function<CWindowOverridableVar<float>*(PHLWINDOW)>> floatWindowProperties = {
|
||||
{"roundingpower", [](const PHLWINDOW& pWindow) { return &pWindow->m_sWindowData.roundingPower; }},
|
||||
{"scrollmouse", [](const PHLWINDOW& pWindow) { return &pWindow->m_sWindowData.scrollMouse; }},
|
||||
{"scrolltouchpad", [](const PHLWINDOW& pWindow) { return &pWindow->m_sWindowData.scrollTouchpad; }},
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
format specification
|
||||
- 'x', only address, equivalent of (uintpr_t)CWindow*
|
||||
|
@@ -5,20 +5,19 @@
|
||||
#include "../config/ConfigManager.hpp"
|
||||
|
||||
static const auto RULES = std::unordered_set<std::string>{
|
||||
"float", "fullscreen", "maximize", "noinitialfocus", "pin", "stayfocused", "tile", "renderunfocused", "persistentsize",
|
||||
"float", "fullscreen", "maximize", "noinitialfocus", "pin", "stayfocused", "tile", "renderunfocused",
|
||||
};
|
||||
static const auto RULES_PREFIX = std::unordered_set<std::string>{
|
||||
"animation", "bordercolor", "bordersize", "center", "content", "fullscreenstate", "group", "idleinhibit", "maxsize", "minsize",
|
||||
"monitor", "move", "opacity", "plugin:", "prop", "pseudo", "rounding", "roundingpower", "scrollmouse", "scrolltouchpad",
|
||||
"size", "suppressevent", "tag", "workspace", "xray",
|
||||
"animation", "bordercolor", "bordersize", "center", "fullscreenstate", "group", "idleinhibit", "maxsize", "minsize", "monitor", "move", "opacity",
|
||||
"plugin:", "prop", "pseudo", "rounding", "roundingpower", "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); }) ||
|
||||
(NWindowProperties::boolWindowProperties.find(VALS[0]) != NWindowProperties::boolWindowProperties.end()) ||
|
||||
(NWindowProperties::intWindowProperties.find(VALS[0]) != NWindowProperties::intWindowProperties.end()) ||
|
||||
(NWindowProperties::floatWindowProperties.find(VALS[0]) != NWindowProperties::floatWindowProperties.end());
|
||||
(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;
|
||||
@@ -39,8 +38,6 @@ CWindowRule::CWindowRule(const std::string& rule, const std::string& value, bool
|
||||
ruleType = RULE_TILE;
|
||||
else if (rule == "renderunfocused")
|
||||
ruleType = RULE_RENDERUNFOCUSED;
|
||||
else if (rule == "persistentsize")
|
||||
ruleType = RULE_PERSISTENTSIZE;
|
||||
else if (rule.starts_with("animation"))
|
||||
ruleType = RULE_ANIMATION;
|
||||
else if (rule.starts_with("bordercolor"))
|
||||
@@ -77,14 +74,12 @@ CWindowRule::CWindowRule(const std::string& rule, const std::string& value, bool
|
||||
ruleType = RULE_WORKSPACE;
|
||||
else if (rule.starts_with("prop"))
|
||||
ruleType = RULE_PROP;
|
||||
else if (rule.starts_with("content"))
|
||||
ruleType = RULE_CONTENT;
|
||||
else {
|
||||
// check if this is a prop.
|
||||
const CVarList VARS(rule, 0, 's', true);
|
||||
if (NWindowProperties::intWindowProperties.find(VARS[0]) != NWindowProperties::intWindowProperties.end() ||
|
||||
NWindowProperties::boolWindowProperties.find(VARS[0]) != NWindowProperties::boolWindowProperties.end() ||
|
||||
NWindowProperties::floatWindowProperties.find(VARS[0]) != NWindowProperties::floatWindowProperties.end()) {
|
||||
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);
|
||||
|
@@ -36,8 +36,6 @@ class CWindowRule {
|
||||
RULE_TAG,
|
||||
RULE_WORKSPACE,
|
||||
RULE_PROP,
|
||||
RULE_CONTENT,
|
||||
RULE_PERSISTENTSIZE,
|
||||
};
|
||||
|
||||
eRuleType ruleType = RULE_INVALID;
|
||||
@@ -60,7 +58,6 @@ class CWindowRule {
|
||||
std::string szFullscreenState = ""; // empty means any
|
||||
std::string szOnWorkspace = ""; // empty means any
|
||||
std::string szWorkspace = ""; // empty means any
|
||||
std::string szContentType = ""; // empty means any
|
||||
|
||||
// precompiled regexes
|
||||
CRuleRegexContainer rTitle;
|
||||
|
@@ -261,7 +261,6 @@ bool CWorkspace::matchesStaticSelector(const std::string& selector_) {
|
||||
// n - named: n[true] or n[s:string] or n[e:string]
|
||||
// m - monitor: m[monitor_selector]
|
||||
// w - windowCount: w[1-4] or w[1], optional flag t or f for tiled or floating and
|
||||
// flag p to count only pinned windows, e.g. w[p1-2], w[pg4]
|
||||
// flag g to count groups instead of windows, e.g. w[t1-2], w[fg4]
|
||||
// flag v will count only visible windows
|
||||
// f - fullscreen state : f[-1], f[0], f[1], or f[2] for different fullscreen states
|
||||
@@ -371,7 +370,6 @@ bool CWorkspace::matchesStaticSelector(const std::string& selector_) {
|
||||
prop = prop.substr(2, prop.length() - 3);
|
||||
|
||||
int wantsOnlyTiled = -1;
|
||||
int wantsOnlyPinned = false;
|
||||
bool wantsCountGroup = false;
|
||||
bool wantsCountVisible = false;
|
||||
|
||||
@@ -383,9 +381,6 @@ bool CWorkspace::matchesStaticSelector(const std::string& selector_) {
|
||||
} else if (flag == 'f' && wantsOnlyTiled == -1) {
|
||||
wantsOnlyTiled = 0;
|
||||
flagCount++;
|
||||
} else if (flag == 'p' && !wantsOnlyPinned) {
|
||||
wantsOnlyPinned = true;
|
||||
flagCount++;
|
||||
} else if (flag == 'g' && !wantsCountGroup) {
|
||||
wantsCountGroup = true;
|
||||
flagCount++;
|
||||
@@ -416,11 +411,9 @@ bool CWorkspace::matchesStaticSelector(const std::string& selector_) {
|
||||
int count;
|
||||
if (wantsCountGroup)
|
||||
count = getGroups(wantsOnlyTiled == -1 ? std::nullopt : std::optional<bool>((bool)wantsOnlyTiled),
|
||||
wantsOnlyPinned ? std::optional<bool>(wantsOnlyPinned) : std::nullopt,
|
||||
wantsCountVisible ? std::optional<bool>(wantsCountVisible) : std::nullopt);
|
||||
else
|
||||
count = getWindows(wantsOnlyTiled == -1 ? std::nullopt : std::optional<bool>((bool)wantsOnlyTiled),
|
||||
wantsOnlyPinned ? std::optional<bool>(wantsOnlyPinned) : std::nullopt,
|
||||
wantsCountVisible ? std::optional<bool>(wantsCountVisible) : std::nullopt);
|
||||
|
||||
if (count != from)
|
||||
@@ -451,12 +444,10 @@ bool CWorkspace::matchesStaticSelector(const std::string& selector_) {
|
||||
|
||||
WORKSPACEID count;
|
||||
if (wantsCountGroup)
|
||||
count =
|
||||
getGroups(wantsOnlyTiled == -1 ? std::nullopt : std::optional<bool>((bool)wantsOnlyTiled),
|
||||
wantsOnlyPinned ? std::optional<bool>(wantsOnlyPinned) : std::nullopt, 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 = getWindows(wantsOnlyTiled == -1 ? std::nullopt : std::optional<bool>((bool)wantsOnlyTiled),
|
||||
wantsOnlyPinned ? std::optional<bool>(wantsOnlyPinned) : std::nullopt,
|
||||
wantsCountVisible ? std::optional<bool>(wantsCountVisible) : std::nullopt);
|
||||
|
||||
if (std::clamp(count, from, to) != count)
|
||||
@@ -544,15 +535,13 @@ bool CWorkspace::isVisibleNotCovered() {
|
||||
return PMONITOR->activeWorkspace->m_iID == m_iID;
|
||||
}
|
||||
|
||||
int CWorkspace::getWindows(std::optional<bool> onlyTiled, std::optional<bool> onlyPinned, std::optional<bool> onlyVisible) {
|
||||
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 (onlyPinned.has_value() && w->m_bPinned != onlyPinned.value())
|
||||
continue;
|
||||
if (onlyVisible.has_value() && w->isHidden() == onlyVisible.value())
|
||||
continue;
|
||||
no++;
|
||||
@@ -561,7 +550,7 @@ int CWorkspace::getWindows(std::optional<bool> onlyTiled, std::optional<bool> on
|
||||
return no;
|
||||
}
|
||||
|
||||
int CWorkspace::getGroups(std::optional<bool> onlyTiled, std::optional<bool> onlyPinned, std::optional<bool> onlyVisible) {
|
||||
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)
|
||||
@@ -570,8 +559,6 @@ int CWorkspace::getGroups(std::optional<bool> onlyTiled, std::optional<bool> onl
|
||||
continue;
|
||||
if (onlyTiled.has_value() && w->m_bIsFloating == onlyTiled.value())
|
||||
continue;
|
||||
if (onlyPinned.has_value() && w->m_bPinned != onlyPinned.value())
|
||||
continue;
|
||||
if (onlyVisible.has_value() && w->isHidden() == onlyVisible.value())
|
||||
continue;
|
||||
no++;
|
||||
@@ -637,7 +624,7 @@ void CWorkspace::forceReportSizesToWindows() {
|
||||
if (w->m_pWorkspace != m_pSelf || !w->m_bIsMapped || w->isHidden())
|
||||
continue;
|
||||
|
||||
w->sendWindowSize(true);
|
||||
w->sendWindowSize(w->m_vRealSize->goal(), true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -648,12 +635,6 @@ void CWorkspace::rename(const std::string& name) {
|
||||
Debug::log(LOG, "CWorkspace::rename: Renaming workspace {} to '{}'", m_iID, name);
|
||||
m_szName = name;
|
||||
|
||||
const auto WORKSPACERULE = g_pConfigManager->getWorkspaceRuleFor(m_pSelf.lock());
|
||||
m_bPersistent = WORKSPACERULE.isPersistent;
|
||||
|
||||
if (WORKSPACERULE.isPersistent)
|
||||
g_pCompositor->ensurePersistentWorkspacesPresent(std::vector<SWorkspaceRule>{WORKSPACERULE}, m_pSelf.lock());
|
||||
|
||||
g_pEventManager->postEvent({"renameworkspace", std::to_string(m_iID) + "," + m_szName});
|
||||
}
|
||||
|
||||
|
@@ -72,8 +72,8 @@ class CWorkspace {
|
||||
SWorkspaceIDName getPrevWorkspaceIDName() const;
|
||||
void updateWindowDecos();
|
||||
void updateWindowData();
|
||||
int getWindows(std::optional<bool> onlyTiled = {}, std::optional<bool> onlyPinned = {}, std::optional<bool> onlyVisible = {});
|
||||
int getGroups(std::optional<bool> onlyTiled = {}, std::optional<bool> onlyPinned = {}, std::optional<bool> onlyVisible = {});
|
||||
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();
|
||||
|
@@ -8,8 +8,6 @@
|
||||
#include <aquamarine/input/Input.hpp>
|
||||
#include <cstring>
|
||||
|
||||
using namespace Hyprutils::OS;
|
||||
|
||||
#define LED_COUNT 3
|
||||
|
||||
constexpr static std::array<const char*, 8> MODNAMES = {
|
||||
@@ -43,6 +41,9 @@ void IKeyboard::clearManuallyAllocd() {
|
||||
if (xkbKeymap)
|
||||
xkb_keymap_unref(xkbKeymap);
|
||||
|
||||
if (xkbKeymapFD >= 0)
|
||||
close(xkbKeymapFD);
|
||||
|
||||
if (xkbSymState)
|
||||
xkb_state_unref(xkbSymState);
|
||||
|
||||
@@ -50,7 +51,7 @@ void IKeyboard::clearManuallyAllocd() {
|
||||
xkbKeymap = nullptr;
|
||||
xkbState = nullptr;
|
||||
xkbStaticState = nullptr;
|
||||
xkbKeymapFD.reset();
|
||||
xkbKeymapFD = -1;
|
||||
}
|
||||
|
||||
void IKeyboard::setKeymap(const SStringRuleNames& rules) {
|
||||
@@ -126,14 +127,14 @@ void IKeyboard::setKeymap(const SStringRuleNames& rules) {
|
||||
updateModifiers(0, 0, modifiersState.locked, modifiersState.group);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < std::min(LEDNAMES.size(), ledIndexes.size()); ++i) {
|
||||
ledIndexes[i] = xkb_map_led_get_index(xkbKeymap, LEDNAMES[i]);
|
||||
Debug::log(LOG, "xkb: LED index {} (name {}) got index {}", i, LEDNAMES[i], ledIndexes[i]);
|
||||
for (size_t i = 0; i < LEDNAMES.size(); ++i) {
|
||||
ledIndexes.at(i) = xkb_map_led_get_index(xkbKeymap, LEDNAMES.at(i));
|
||||
Debug::log(LOG, "xkb: LED index {} (name {}) got index {}", i, LEDNAMES.at(i), ledIndexes.at(i));
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < std::min(MODNAMES.size(), modIndexes.size()); ++i) {
|
||||
modIndexes[i] = xkb_map_mod_get_index(xkbKeymap, MODNAMES[i]);
|
||||
Debug::log(LOG, "xkb: Mod index {} (name {}) got index {}", i, MODNAMES[i], modIndexes[i]);
|
||||
for (size_t i = 0; i < MODNAMES.size(); ++i) {
|
||||
modIndexes.at(i) = xkb_map_mod_get_index(xkbKeymap, MODNAMES.at(i));
|
||||
Debug::log(LOG, "xkb: Mod index {} (name {}) got index {}", i, MODNAMES.at(i), modIndexes.at(i));
|
||||
}
|
||||
|
||||
updateKeymapFD();
|
||||
@@ -146,30 +147,31 @@ void IKeyboard::setKeymap(const SStringRuleNames& rules) {
|
||||
void IKeyboard::updateKeymapFD() {
|
||||
Debug::log(LOG, "Updating keymap fd for keyboard {}", deviceName);
|
||||
|
||||
if (xkbKeymapFD.isValid())
|
||||
xkbKeymapFD.reset();
|
||||
if (xkbKeymapFD >= 0)
|
||||
close(xkbKeymapFD);
|
||||
xkbKeymapFD = -1;
|
||||
|
||||
auto cKeymapStr = xkb_keymap_get_as_string(xkbKeymap, XKB_KEYMAP_FORMAT_TEXT_V1);
|
||||
xkbKeymapString = cKeymapStr;
|
||||
free(cKeymapStr);
|
||||
|
||||
CFileDescriptor rw, ro;
|
||||
if (!allocateSHMFilePair(xkbKeymapString.length() + 1, rw, ro))
|
||||
int rw, ro;
|
||||
if (!allocateSHMFilePair(xkbKeymapString.length() + 1, &rw, &ro))
|
||||
Debug::log(ERR, "IKeyboard: failed to allocate shm pair for the keymap");
|
||||
else {
|
||||
auto keymapFDDest = mmap(nullptr, xkbKeymapString.length() + 1, PROT_READ | PROT_WRITE, MAP_SHARED, rw.get(), 0);
|
||||
rw.reset();
|
||||
auto keymapFDDest = mmap(nullptr, xkbKeymapString.length() + 1, PROT_READ | PROT_WRITE, MAP_SHARED, rw, 0);
|
||||
close(rw);
|
||||
if (keymapFDDest == MAP_FAILED) {
|
||||
Debug::log(ERR, "IKeyboard: failed to mmap a shm pair for the keymap");
|
||||
ro.reset();
|
||||
close(ro);
|
||||
} else {
|
||||
memcpy(keymapFDDest, xkbKeymapString.c_str(), xkbKeymapString.length());
|
||||
munmap(keymapFDDest, xkbKeymapString.length() + 1);
|
||||
xkbKeymapFD = std::move(ro);
|
||||
xkbKeymapFD = ro;
|
||||
}
|
||||
}
|
||||
|
||||
Debug::log(LOG, "Updated keymap fd to {}", xkbKeymapFD.get());
|
||||
Debug::log(LOG, "Updated keymap fd to {}", xkbKeymapFD);
|
||||
}
|
||||
|
||||
void IKeyboard::updateXKBTranslationState(xkb_keymap* const keymap) {
|
||||
@@ -289,8 +291,8 @@ std::optional<uint32_t> IKeyboard::getLEDs() {
|
||||
return {};
|
||||
|
||||
uint32_t leds = 0;
|
||||
for (uint32_t i = 0; i < std::min((size_t)LED_COUNT, ledIndexes.size()); ++i) {
|
||||
if (xkb_state_led_index_is_active(xkbState, ledIndexes[i]))
|
||||
for (uint32_t i = 0; i < LED_COUNT; ++i) {
|
||||
if (xkb_state_led_index_is_active(xkbState, ledIndexes.at(i)))
|
||||
leds |= (1 << i);
|
||||
}
|
||||
|
||||
@@ -323,10 +325,10 @@ uint32_t IKeyboard::getModifiers() {
|
||||
uint32_t modMask = modifiersState.depressed | modifiersState.latched;
|
||||
uint32_t mods = 0;
|
||||
for (size_t i = 0; i < modIndexes.size(); ++i) {
|
||||
if (modIndexes[i] == XKB_MOD_INVALID)
|
||||
if (modIndexes.at(i) == XKB_MOD_INVALID)
|
||||
continue;
|
||||
|
||||
if (!(modMask & (1 << modIndexes[i])))
|
||||
if (!(modMask & (1 << modIndexes.at(i))))
|
||||
continue;
|
||||
|
||||
mods |= (1 << i);
|
||||
|
@@ -6,7 +6,6 @@
|
||||
|
||||
#include <optional>
|
||||
#include <xkbcommon/xkbcommon.h>
|
||||
#include <hyprutils/os/FileDescriptor.hpp>
|
||||
|
||||
AQUAMARINE_FORWARD(IKeyboard);
|
||||
|
||||
@@ -97,7 +96,7 @@ class IKeyboard : public IHID {
|
||||
|
||||
std::string xkbFilePath = "";
|
||||
std::string xkbKeymapString = "";
|
||||
Hyprutils::OS::CFileDescriptor xkbKeymapFD;
|
||||
int xkbKeymapFD = -1;
|
||||
|
||||
SStringRuleNames currentRules;
|
||||
int repeatRate = 0;
|
||||
|
@@ -17,10 +17,9 @@ class IPointer : public IHID {
|
||||
virtual SP<Aquamarine::IPointer> aq() = 0;
|
||||
|
||||
struct SMotionEvent {
|
||||
uint32_t timeMs = 0;
|
||||
Vector2D delta, unaccel;
|
||||
bool mouse = false;
|
||||
SP<IPointer> device;
|
||||
uint32_t timeMs = 0;
|
||||
Vector2D delta, unaccel;
|
||||
bool mouse = false;
|
||||
};
|
||||
|
||||
struct SMotionAbsoluteEvent {
|
||||
@@ -110,9 +109,6 @@ class IPointer : public IHID {
|
||||
|
||||
bool connected = false; // means connected to the cursor
|
||||
std::string boundOutput = "";
|
||||
bool flipX = false; // decide to invert horizontal movement
|
||||
bool flipY = false; // decide to invert vertical movement
|
||||
bool isTouchpad = false;
|
||||
|
||||
WP<IPointer> self;
|
||||
};
|
||||
|
@@ -14,11 +14,6 @@ CMouse::CMouse(SP<Aquamarine::IPointer> mouse_) : mouse(mouse_) {
|
||||
if (!mouse)
|
||||
return;
|
||||
|
||||
if (auto handle = mouse->getLibinputHandle()) {
|
||||
double w = 0, h = 0;
|
||||
isTouchpad = libinput_device_has_capability(handle, LIBINPUT_DEVICE_CAP_POINTER) && libinput_device_get_size(handle, &w, &h) == 0;
|
||||
}
|
||||
|
||||
listeners.destroy = mouse->events.destroy.registerListener([this](std::any d) {
|
||||
mouse.reset();
|
||||
events.destroy.emit();
|
||||
@@ -32,7 +27,6 @@ CMouse::CMouse(SP<Aquamarine::IPointer> mouse_) : mouse(mouse_) {
|
||||
.delta = E.delta,
|
||||
.unaccel = E.unaccel,
|
||||
.mouse = true,
|
||||
.device = self.lock(),
|
||||
});
|
||||
});
|
||||
|
||||
|
@@ -19,11 +19,7 @@ CVirtualPointer::CVirtualPointer(SP<CVirtualPointerV1Resource> resource) : point
|
||||
events.destroy.emit();
|
||||
});
|
||||
|
||||
listeners.motion = pointer->events.move.registerListener([this](std::any d) {
|
||||
auto E = std::any_cast<SMotionEvent>(d);
|
||||
E.device = self.lock();
|
||||
pointerEvents.motion.emit(E);
|
||||
});
|
||||
listeners.motion = pointer->events.move.registerListener([this](std::any d) { pointerEvents.motion.emit(d); });
|
||||
listeners.motionAbsolute = pointer->events.warp.registerListener([this](std::any d) {
|
||||
// we need to unpack the event and add our device here because it's required to calculate the position correctly
|
||||
auto E = std::any_cast<SMotionAbsoluteEvent>(d);
|
||||
|
@@ -11,11 +11,11 @@
|
||||
#include "../protocols/XDGShell.hpp"
|
||||
#include "../protocols/core/Compositor.hpp"
|
||||
#include "../protocols/ToplevelExport.hpp"
|
||||
#include "../protocols/types/ContentType.hpp"
|
||||
#include "../xwayland/XSurface.hpp"
|
||||
#include "managers/AnimationManager.hpp"
|
||||
#include "managers/PointerManager.hpp"
|
||||
#include "../desktop/LayerSurface.hpp"
|
||||
#include "../managers/input/InputManager.hpp"
|
||||
#include "../managers/LayoutManager.hpp"
|
||||
#include "../managers/EventManager.hpp"
|
||||
#include "../managers/AnimationManager.hpp"
|
||||
@@ -307,13 +307,6 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CWindowRule::RULE_CONTENT: {
|
||||
const CVarList VARS(r->szRule, 0, ' ');
|
||||
try {
|
||||
PWINDOW->setContentType(NContentType::fromString(VARS[1]));
|
||||
} catch (std::exception& e) { Debug::log(ERR, "Rule \"{}\" failed with: {}", r->szRule, e.what()); }
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
|
||||
@@ -349,7 +342,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
if (!workspaceSilent) {
|
||||
if (pWorkspace->m_bIsSpecialWorkspace)
|
||||
pWorkspace->m_pMonitor->setSpecialWorkspace(pWorkspace);
|
||||
else if (PMONITOR->activeWorkspaceID() != REQUESTEDWORKSPACEID && !PWINDOW->m_bNoInitialFocus)
|
||||
else if (PMONITOR->activeWorkspaceID() != REQUESTEDWORKSPACEID)
|
||||
g_pKeybindManager->m_mDispatchers["workspace"](requestedWorkspaceName);
|
||||
|
||||
PMONITOR = g_pCompositor->m_pLastMonitor.lock();
|
||||
@@ -392,8 +385,6 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
// Verify window swallowing. Get the swallower before calling onWindowCreated(PWINDOW) because getSwallower() wouldn't get it after if PWINDOW gets auto grouped.
|
||||
const auto SWALLOWER = PWINDOW->getSwallower();
|
||||
PWINDOW->m_pSwallowed = SWALLOWER;
|
||||
if (PWINDOW->m_pSwallowed)
|
||||
PWINDOW->m_pSwallowed->m_bCurrentlySwallowed = true;
|
||||
|
||||
if (PWINDOW->m_bIsFloating) {
|
||||
g_pLayoutManager->getCurrentLayout()->onWindowCreated(PWINDOW);
|
||||
@@ -688,6 +679,13 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
|
||||
if (PMONITOR && PWINDOW->isX11OverrideRedirect())
|
||||
PWINDOW->m_fX11SurfaceScaledBy = PMONITOR->scale;
|
||||
|
||||
// Fix some X11 popups being invisible / having incorrect size on open.
|
||||
// What the ACTUAL FUCK is going on?????? I HATE X11
|
||||
if (!PWINDOW->isX11OverrideRedirect() && PWINDOW->m_bIsX11 && PWINDOW->m_bIsFloating) {
|
||||
PWINDOW->sendWindowSize(PWINDOW->m_vRealSize->goal(), true, PWINDOW->m_vRealPosition->goal() - Vector2D{1, 1});
|
||||
PWINDOW->sendWindowSize(PWINDOW->m_vRealSize->goal(), true);
|
||||
}
|
||||
}
|
||||
|
||||
void Events::listener_unmapWindow(void* owner, void* data) {
|
||||
@@ -716,13 +714,6 @@ void Events::listener_unmapWindow(void* owner, void* data) {
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"closewindow", std::format("{:x}", PWINDOW)});
|
||||
EMIT_HOOK_EVENT("closeWindow", PWINDOW);
|
||||
|
||||
if (PWINDOW->m_bIsFloating && !PWINDOW->m_bIsX11 &&
|
||||
std::any_of(PWINDOW->m_vMatchedRules.begin(), PWINDOW->m_vMatchedRules.end(), [](const auto& r) { return r->ruleType == CWindowRule::RULE_PERSISTENTSIZE; })) {
|
||||
Debug::log(LOG, "storing floating size {}x{} for window {}::{} on close", PWINDOW->m_vRealSize->value().x, PWINDOW->m_vRealSize->value().y, PWINDOW->m_szClass,
|
||||
PWINDOW->m_szTitle);
|
||||
g_pConfigManager->storeFloatingSize(PWINDOW, PWINDOW->m_vRealSize->value());
|
||||
}
|
||||
|
||||
PROTO::toplevelExport->onWindowUnmap(PWINDOW);
|
||||
|
||||
if (PWINDOW->isFullscreen())
|
||||
@@ -733,15 +724,12 @@ void Events::listener_unmapWindow(void* owner, void* data) {
|
||||
|
||||
// swallowing
|
||||
if (valid(PWINDOW->m_pSwallowed)) {
|
||||
if (PWINDOW->m_pSwallowed->m_bCurrentlySwallowed) {
|
||||
PWINDOW->m_pSwallowed->m_bCurrentlySwallowed = false;
|
||||
PWINDOW->m_pSwallowed->setHidden(false);
|
||||
PWINDOW->m_pSwallowed->setHidden(false);
|
||||
|
||||
if (PWINDOW->m_sGroupData.pNextWindow.lock())
|
||||
PWINDOW->m_pSwallowed->m_bGroupSwallowed = true; // flag for the swallowed window to be created into the group where it belongs when auto_group = false.
|
||||
if (PWINDOW->m_sGroupData.pNextWindow.lock())
|
||||
PWINDOW->m_pSwallowed->m_bGroupSwallowed = true; // flag for the swallowed window to be created into the group where it belongs when auto_group = false.
|
||||
|
||||
g_pLayoutManager->getCurrentLayout()->onWindowCreated(PWINDOW->m_pSwallowed.lock());
|
||||
}
|
||||
g_pLayoutManager->getCurrentLayout()->onWindowCreated(PWINDOW->m_pSwallowed.lock());
|
||||
|
||||
PWINDOW->m_pSwallowed->m_bGroupSwallowed = false;
|
||||
PWINDOW->m_pSwallowed.reset();
|
||||
@@ -880,7 +868,7 @@ void Events::listener_commitWindow(void* owner, void* data) {
|
||||
|
||||
// tearing: if solitary, redraw it. This still might be a single surface window
|
||||
if (PMONITOR && PMONITOR->solitaryClient.lock() == PWINDOW && PWINDOW->canBeTorn() && PMONITOR->tearingState.canTear && PWINDOW->m_pWLSurface->resource()->current.texture) {
|
||||
CRegion damageBox{PWINDOW->m_pWLSurface->resource()->current.accumulateBufferDamage()};
|
||||
CRegion damageBox{PWINDOW->m_pWLSurface->resource()->accumulateCurrentBufferDamage()};
|
||||
|
||||
if (!damageBox.empty()) {
|
||||
if (PMONITOR->tearingState.busy) {
|
||||
@@ -964,7 +952,7 @@ void Events::listener_unmanagedSetGeometry(void* owner, void* data) {
|
||||
PWINDOW->setHidden(true);
|
||||
|
||||
if (PWINDOW->isFullscreen() || !PWINDOW->m_bIsFloating) {
|
||||
PWINDOW->sendWindowSize(true);
|
||||
PWINDOW->sendWindowSize(PWINDOW->m_vRealSize->goal(), true);
|
||||
g_pHyprRenderer->damageWindow(PWINDOW);
|
||||
return;
|
||||
}
|
||||
|
@@ -49,6 +49,97 @@ using namespace Hyprutils::OS;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static const float transforms[][9] = {
|
||||
{
|
||||
1.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
1.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
1.0f,
|
||||
},
|
||||
{
|
||||
0.0f,
|
||||
1.0f,
|
||||
0.0f,
|
||||
-1.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
1.0f,
|
||||
},
|
||||
{
|
||||
-1.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
-1.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
1.0f,
|
||||
},
|
||||
{
|
||||
0.0f,
|
||||
-1.0f,
|
||||
0.0f,
|
||||
1.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
1.0f,
|
||||
},
|
||||
{
|
||||
-1.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
1.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
1.0f,
|
||||
},
|
||||
{
|
||||
0.0f,
|
||||
1.0f,
|
||||
0.0f,
|
||||
1.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
1.0f,
|
||||
},
|
||||
{
|
||||
1.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
-1.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
1.0f,
|
||||
},
|
||||
{
|
||||
0.0f,
|
||||
-1.0f,
|
||||
0.0f,
|
||||
-1.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
1.0f,
|
||||
},
|
||||
};
|
||||
|
||||
std::string absolutePath(const std::string& rawpath, const std::string& currentPath) {
|
||||
auto value = rawpath;
|
||||
|
||||
@@ -745,48 +836,50 @@ bool envEnabled(const std::string& env) {
|
||||
return std::string(ENV) == "1";
|
||||
}
|
||||
|
||||
std::pair<CFileDescriptor, std::string> openExclusiveShm() {
|
||||
std::pair<int, std::string> openExclusiveShm() {
|
||||
// Only absolute paths can be shared across different shm_open() calls
|
||||
std::string name = "/" + g_pTokenManager->getRandomUUID();
|
||||
|
||||
for (size_t i = 0; i < 69; ++i) {
|
||||
CFileDescriptor fd{shm_open(name.c_str(), O_RDWR | O_CREAT | O_EXCL, 0600)};
|
||||
if (fd.isValid())
|
||||
return {std::move(fd), name};
|
||||
int fd = shm_open(name.c_str(), O_RDWR | O_CREAT | O_EXCL, 0600);
|
||||
if (fd >= 0)
|
||||
return {fd, name};
|
||||
}
|
||||
|
||||
return {{}, ""};
|
||||
return {-1, ""};
|
||||
}
|
||||
|
||||
CFileDescriptor allocateSHMFile(size_t len) {
|
||||
int allocateSHMFile(size_t len) {
|
||||
auto [fd, name] = openExclusiveShm();
|
||||
if (!fd.isValid())
|
||||
return {};
|
||||
if (fd < 0)
|
||||
return -1;
|
||||
|
||||
shm_unlink(name.c_str());
|
||||
|
||||
int ret;
|
||||
do {
|
||||
ret = ftruncate(fd.get(), len);
|
||||
ret = ftruncate(fd, len);
|
||||
} while (ret < 0 && errno == EINTR);
|
||||
|
||||
if (ret < 0) {
|
||||
return {};
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return std::move(fd);
|
||||
return fd;
|
||||
}
|
||||
|
||||
bool allocateSHMFilePair(size_t size, CFileDescriptor& rw_fd_ptr, CFileDescriptor& ro_fd_ptr) {
|
||||
bool allocateSHMFilePair(size_t size, int* rw_fd_ptr, int* ro_fd_ptr) {
|
||||
auto [fd, name] = openExclusiveShm();
|
||||
if (!fd.isValid()) {
|
||||
if (fd < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// CLOEXEC is guaranteed to be set by shm_open
|
||||
CFileDescriptor ro_fd{shm_open(name.c_str(), O_RDONLY, 0)};
|
||||
if (!ro_fd.isValid()) {
|
||||
int ro_fd = shm_open(name.c_str(), O_RDONLY, 0);
|
||||
if (ro_fd < 0) {
|
||||
shm_unlink(name.c_str());
|
||||
close(fd);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -794,20 +887,24 @@ bool allocateSHMFilePair(size_t size, CFileDescriptor& rw_fd_ptr, CFileDescripto
|
||||
|
||||
// Make sure the file cannot be re-opened in read-write mode (e.g. via
|
||||
// "/proc/self/fd/" on Linux)
|
||||
if (fchmod(fd.get(), 0) != 0) {
|
||||
if (fchmod(fd, 0) != 0) {
|
||||
close(fd);
|
||||
close(ro_fd);
|
||||
return false;
|
||||
}
|
||||
|
||||
int ret;
|
||||
do {
|
||||
ret = ftruncate(fd.get(), size);
|
||||
ret = ftruncate(fd, size);
|
||||
} while (ret < 0 && errno == EINTR);
|
||||
if (ret < 0) {
|
||||
close(fd);
|
||||
close(ro_fd);
|
||||
return false;
|
||||
}
|
||||
|
||||
rw_fd_ptr = std::move(fd);
|
||||
ro_fd_ptr = std::move(ro_fd);
|
||||
*rw_fd_ptr = fd;
|
||||
*ro_fd_ptr = ro_fd;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@@ -5,7 +5,6 @@
|
||||
#include <vector>
|
||||
#include <format>
|
||||
#include <expected>
|
||||
#include <hyprutils/os/FileDescriptor.hpp>
|
||||
#include "../SharedDefs.hpp"
|
||||
#include "../macros.hpp"
|
||||
|
||||
@@ -36,8 +35,8 @@ double normalizeAngleRad(double ang);
|
||||
std::vector<SCallstackFrameInfo> getBacktrace();
|
||||
void throwError(const std::string& err);
|
||||
bool envEnabled(const std::string& env);
|
||||
Hyprutils::OS::CFileDescriptor allocateSHMFile(size_t len);
|
||||
bool allocateSHMFilePair(size_t size, Hyprutils::OS::CFileDescriptor& rw_fd_ptr, Hyprutils::OS::CFileDescriptor& ro_fd_ptr);
|
||||
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);
|
||||
|
||||
template <typename... Args>
|
||||
|
@@ -2,7 +2,6 @@
|
||||
#include "MiscFunctions.hpp"
|
||||
#include "../macros.hpp"
|
||||
#include "math/Math.hpp"
|
||||
#include "../protocols/ColorManagement.hpp"
|
||||
#include "sync/SyncReleaser.hpp"
|
||||
#include "../Compositor.hpp"
|
||||
#include "../config/ConfigValue.hpp"
|
||||
@@ -33,8 +32,6 @@
|
||||
#include <ranges>
|
||||
using namespace Hyprutils::String;
|
||||
using namespace Hyprutils::Utils;
|
||||
using namespace Hyprutils::OS;
|
||||
using enum NContentType::eContentType;
|
||||
|
||||
static int ratHandler(void* data) {
|
||||
g_pHyprRenderer->renderMonitor(((CMonitor*)data)->self.lock());
|
||||
@@ -57,7 +54,8 @@ void CMonitor::onConnect(bool noRule) {
|
||||
g_pEventLoopManager->doLater([] { g_pConfigManager->ensurePersistentWorkspacesPresent(); });
|
||||
|
||||
if (output->supportsExplicit) {
|
||||
inTimeline = CSyncTimeline::create(output->getBackend()->drmFD());
|
||||
inTimeline = CSyncTimeline::create(output->getBackend()->drmFD());
|
||||
outTimeline = CSyncTimeline::create(output->getBackend()->drmFD());
|
||||
}
|
||||
|
||||
listeners.frame = output->events.frame.registerListener([this](std::any d) { onMonitorFrame(); });
|
||||
@@ -412,8 +410,7 @@ bool CMonitor::applyMonitorRule(SMonitorRule* pMonitorRule, bool force) {
|
||||
if (!force && DELTALESSTHAN(vecPixelSize.x, RULE->resolution.x, 1) && DELTALESSTHAN(vecPixelSize.y, RULE->resolution.y, 1) &&
|
||||
DELTALESSTHAN(refreshRate, RULE->refreshRate, 1) && setScale == RULE->scale &&
|
||||
((DELTALESSTHAN(vecPosition.x, RULE->offset.x, 1) && DELTALESSTHAN(vecPosition.y, RULE->offset.y, 1)) || RULE->offset == Vector2D(-INT32_MAX, -INT32_MAX)) &&
|
||||
transform == RULE->transform && RULE->enable10bit == enabled10bit && RULE->cmType == cmType && RULE->sdrSaturation == sdrSaturation &&
|
||||
RULE->sdrBrightness == sdrBrightness && !std::memcmp(&customDrmMode, &RULE->drmMode, sizeof(customDrmMode))) {
|
||||
transform == RULE->transform && RULE->enable10bit == enabled10bit && !std::memcmp(&customDrmMode, &RULE->drmMode, sizeof(customDrmMode))) {
|
||||
|
||||
Debug::log(LOG, "Not applying a new rule to {} because it's already applied!", szName);
|
||||
|
||||
@@ -671,66 +668,6 @@ bool CMonitor::applyMonitorRule(SMonitorRule* pMonitorRule, bool force) {
|
||||
|
||||
enabled10bit = set10bit;
|
||||
|
||||
auto oldImageDescription = imageDescription;
|
||||
cmType = RULE->cmType;
|
||||
switch (cmType) {
|
||||
case CM_AUTO: cmType = enabled10bit && output->parsedEDID.supportsBT2020 ? CM_WIDE : CM_SRGB; break;
|
||||
case CM_EDID: cmType = output->parsedEDID.chromaticityCoords.has_value() ? CM_EDID : CM_SRGB; break;
|
||||
case CM_HDR:
|
||||
case CM_HDR_EDID:
|
||||
cmType = output->parsedEDID.supportsBT2020 && output->parsedEDID.hdrMetadata.has_value() && output->parsedEDID.hdrMetadata->supportsPQ ? cmType : CM_SRGB;
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
switch (cmType) {
|
||||
case CM_SRGB: imageDescription = {}; break; // assumes SImageDescirption defaults to sRGB
|
||||
case CM_WIDE:
|
||||
imageDescription = {.primariesNameSet = true,
|
||||
.primariesNamed = NColorManagement::CM_PRIMARIES_BT2020,
|
||||
.primaries = NColorManagement::getPrimaries(NColorManagement::CM_PRIMARIES_BT2020)};
|
||||
break;
|
||||
case CM_EDID:
|
||||
imageDescription = {.primariesNameSet = false,
|
||||
.primariesNamed = NColorManagement::CM_PRIMARIES_BT2020,
|
||||
.primaries = {
|
||||
.red = {.x = output->parsedEDID.chromaticityCoords->red.x, .y = output->parsedEDID.chromaticityCoords->red.y},
|
||||
.green = {.x = output->parsedEDID.chromaticityCoords->green.x, .y = output->parsedEDID.chromaticityCoords->green.y},
|
||||
.blue = {.x = output->parsedEDID.chromaticityCoords->blue.x, .y = output->parsedEDID.chromaticityCoords->blue.y},
|
||||
.white = {.x = output->parsedEDID.chromaticityCoords->white.x, .y = output->parsedEDID.chromaticityCoords->white.y},
|
||||
}};
|
||||
break;
|
||||
case CM_HDR:
|
||||
imageDescription = {.transferFunction = NColorManagement::CM_TRANSFER_FUNCTION_ST2084_PQ,
|
||||
.primariesNameSet = true,
|
||||
.primariesNamed = NColorManagement::CM_PRIMARIES_BT2020,
|
||||
.primaries = NColorManagement::getPrimaries(NColorManagement::CM_PRIMARIES_BT2020),
|
||||
.luminances = {.min = 0, .max = 10000, .reference = 203}};
|
||||
break;
|
||||
case CM_HDR_EDID:
|
||||
imageDescription = {.transferFunction = NColorManagement::CM_TRANSFER_FUNCTION_ST2084_PQ,
|
||||
.primariesNameSet = false,
|
||||
.primariesNamed = NColorManagement::CM_PRIMARIES_BT2020,
|
||||
.primaries = output->parsedEDID.chromaticityCoords.has_value() ?
|
||||
NColorManagement::SPCPRimaries{
|
||||
.red = {.x = output->parsedEDID.chromaticityCoords->red.x, .y = output->parsedEDID.chromaticityCoords->red.y},
|
||||
.green = {.x = output->parsedEDID.chromaticityCoords->green.x, .y = output->parsedEDID.chromaticityCoords->green.y},
|
||||
.blue = {.x = output->parsedEDID.chromaticityCoords->blue.x, .y = output->parsedEDID.chromaticityCoords->blue.y},
|
||||
.white = {.x = output->parsedEDID.chromaticityCoords->white.x, .y = output->parsedEDID.chromaticityCoords->white.y},
|
||||
} :
|
||||
NColorManagement::getPrimaries(NColorManagement::CM_PRIMARIES_BT2020),
|
||||
.luminances = {.min = output->parsedEDID.hdrMetadata->desiredContentMinLuminance,
|
||||
.max = output->parsedEDID.hdrMetadata->desiredContentMaxLuminance,
|
||||
.reference = output->parsedEDID.hdrMetadata->desiredMaxFrameAverageLuminance}};
|
||||
|
||||
break;
|
||||
default: UNREACHABLE();
|
||||
}
|
||||
if (oldImageDescription != imageDescription)
|
||||
PROTO::colorManagement->onMonitorImageDescriptionChanged(self);
|
||||
|
||||
sdrSaturation = RULE->sdrSaturation;
|
||||
sdrBrightness = RULE->sdrBrightness;
|
||||
|
||||
Vector2D logicalSize = vecPixelSize / scale;
|
||||
if (!*PDISABLESCALECHECKS && (logicalSize.x != std::round(logicalSize.x) || logicalSize.y != std::round(logicalSize.y))) {
|
||||
// invalid scale, will produce fractional pixels.
|
||||
@@ -861,8 +798,8 @@ bool CMonitor::shouldSkipScheduleFrameOnMouseEvent() {
|
||||
static auto PMINRR = CConfigValue<Hyprlang::INT>("cursor:min_refresh_rate");
|
||||
|
||||
// skip scheduling extra frames for fullsreen apps with vrr
|
||||
const bool shouldSkip = activeWorkspace && activeWorkspace->m_bHasFullscreenWindow && activeWorkspace->m_efFullscreenMode == FSMODE_FULLSCREEN &&
|
||||
(*PNOBREAK == 1 || (*PNOBREAK == 2 && activeWorkspace->getFullscreenWindow()->getContentType() == CONTENT_TYPE_GAME)) && output->state->state().adaptiveSync;
|
||||
bool shouldSkip =
|
||||
*PNOBREAK && output->state->state().adaptiveSync && activeWorkspace && activeWorkspace->m_bHasFullscreenWindow && activeWorkspace->m_efFullscreenMode == FSMODE_FULLSCREEN;
|
||||
|
||||
// keep requested minimum refresh rate
|
||||
if (shouldSkip && *PMINRR && lastPresentationTimer.getMillis() > 1000.0f / *PMINRR) {
|
||||
@@ -1080,17 +1017,15 @@ void CMonitor::changeWorkspace(const PHLWORKSPACE& pWorkspace, bool internal, bo
|
||||
if (pWorkspace == activeWorkspace)
|
||||
return;
|
||||
|
||||
const auto POLDWORKSPACE = activeWorkspace;
|
||||
if (POLDWORKSPACE)
|
||||
POLDWORKSPACE->m_bVisible = false;
|
||||
pWorkspace->m_bVisible = true;
|
||||
const auto POLDWORKSPACE = activeWorkspace;
|
||||
POLDWORKSPACE->m_bVisible = false;
|
||||
pWorkspace->m_bVisible = true;
|
||||
|
||||
activeWorkspace = pWorkspace;
|
||||
|
||||
if (!internal) {
|
||||
const auto ANIMTOLEFT = POLDWORKSPACE && pWorkspace->m_iID > POLDWORKSPACE->m_iID;
|
||||
if (POLDWORKSPACE)
|
||||
POLDWORKSPACE->startAnim(false, ANIMTOLEFT);
|
||||
const auto ANIMTOLEFT = pWorkspace->m_iID > POLDWORKSPACE->m_iID;
|
||||
POLDWORKSPACE->startAnim(false, ANIMTOLEFT);
|
||||
pWorkspace->startAnim(true, ANIMTOLEFT);
|
||||
|
||||
// move pinned windows
|
||||
@@ -1156,7 +1091,6 @@ void CMonitor::setSpecialWorkspace(const PHLWORKSPACE& pWorkspace) {
|
||||
activeSpecialWorkspace->m_bVisible = false;
|
||||
activeSpecialWorkspace->startAnim(false, false);
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"activespecial", "," + szName});
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"activespecialv2", ",," + szName});
|
||||
}
|
||||
activeSpecialWorkspace.reset();
|
||||
|
||||
@@ -1186,13 +1120,12 @@ void CMonitor::setSpecialWorkspace(const PHLWORKSPACE& pWorkspace) {
|
||||
bool animate = true;
|
||||
//close if open elsewhere
|
||||
const auto PMONITORWORKSPACEOWNER = pWorkspace->m_pMonitor.lock();
|
||||
if (const auto PMWSOWNER = pWorkspace->m_pMonitor.lock(); PMWSOWNER && PMWSOWNER->activeSpecialWorkspace == pWorkspace) {
|
||||
PMWSOWNER->activeSpecialWorkspace.reset();
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PMWSOWNER->ID);
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"activespecial", "," + PMWSOWNER->szName});
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"activespecialv2", ",," + PMWSOWNER->szName});
|
||||
if (PMONITORWORKSPACEOWNER->activeSpecialWorkspace == pWorkspace) {
|
||||
PMONITORWORKSPACEOWNER->activeSpecialWorkspace.reset();
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PMONITORWORKSPACEOWNER->ID);
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"activespecial", "," + PMONITORWORKSPACEOWNER->szName});
|
||||
|
||||
const auto PACTIVEWORKSPACE = PMWSOWNER->activeWorkspace;
|
||||
const auto PACTIVEWORKSPACE = PMONITORWORKSPACEOWNER->activeWorkspace;
|
||||
g_pCompositor->updateFullscreenFadeOnWorkspace(PACTIVEWORKSPACE);
|
||||
|
||||
animate = false;
|
||||
@@ -1239,7 +1172,6 @@ void CMonitor::setSpecialWorkspace(const PHLWORKSPACE& pWorkspace) {
|
||||
}
|
||||
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"activespecial", pWorkspace->m_szName + "," + szName});
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"activespecialv2", std::to_string(pWorkspace->m_iID) + "," + pWorkspace->m_szName + "," + szName});
|
||||
|
||||
g_pHyprRenderer->damageMonitor(self.lock());
|
||||
|
||||
@@ -1341,43 +1273,23 @@ bool CMonitor::attemptDirectScanout() {
|
||||
|
||||
const auto PSURFACE = g_pXWaylandManager->getWindowSurface(PCANDIDATE);
|
||||
|
||||
if (!PSURFACE || !PSURFACE->current.texture || !PSURFACE->current.buffer)
|
||||
return false;
|
||||
|
||||
if (PSURFACE->current.bufferSize != vecPixelSize || PSURFACE->current.transform != transform)
|
||||
if (!PSURFACE || !PSURFACE->current.buffer || PSURFACE->current.bufferSize != vecPixelSize || PSURFACE->current.transform != transform)
|
||||
return false;
|
||||
|
||||
// we can't scanout shm buffers.
|
||||
const auto params = PSURFACE->current.buffer->buffer->dmabuf();
|
||||
if (!params.success || !PSURFACE->current.texture->m_pEglImage /* dmabuf */)
|
||||
if (!PSURFACE->current.buffer || !PSURFACE->current.buffer->buffer || !PSURFACE->current.texture || !PSURFACE->current.texture->m_pEglImage /* dmabuf */)
|
||||
return false;
|
||||
|
||||
Debug::log(TRACE, "attemptDirectScanout: surface {:x} passed, will attempt, buffer {}", (uintptr_t)PSURFACE.get(), (uintptr_t)PSURFACE->current.buffer->buffer.get());
|
||||
|
||||
auto PBUFFER = PSURFACE->current.buffer->buffer;
|
||||
|
||||
if (PBUFFER == output->state->state().buffer) {
|
||||
if (scanoutNeedsCursorUpdate) {
|
||||
if (!state.test()) {
|
||||
Debug::log(TRACE, "attemptDirectScanout: failed basic test");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!output->commit()) {
|
||||
Debug::log(TRACE, "attemptDirectScanout: failed to commit cursor update");
|
||||
lastScanout.reset();
|
||||
return false;
|
||||
}
|
||||
|
||||
scanoutNeedsCursorUpdate = false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
Debug::log(TRACE, "attemptDirectScanout: surface {:x} passed, will attempt", (uintptr_t)PSURFACE.get());
|
||||
|
||||
// FIXME: make sure the buffer actually follows the available scanout dmabuf formats
|
||||
// and comes from the appropriate device. This may implode on multi-gpu!!
|
||||
|
||||
const auto params = PSURFACE->current.buffer->buffer->dmabuf();
|
||||
// scanout buffer isn't dmabuf, so no scanout
|
||||
if (!params.success)
|
||||
return false;
|
||||
|
||||
// entering into scanout, so save monitor format
|
||||
if (lastScanout.expired())
|
||||
prevDrmFormat = drmFormat;
|
||||
@@ -1387,7 +1299,7 @@ bool CMonitor::attemptDirectScanout() {
|
||||
drmFormat = params.format;
|
||||
}
|
||||
|
||||
output->state->setBuffer(PBUFFER);
|
||||
output->state->setBuffer(PSURFACE->current.buffer->buffer.lock());
|
||||
output->state->setPresentationMode(tearingState.activelyTearing ? Aquamarine::eOutputPresentationMode::AQ_OUTPUT_PRESENTATION_IMMEDIATE :
|
||||
Aquamarine::eOutputPresentationMode::AQ_OUTPUT_PRESENTATION_VSYNC);
|
||||
|
||||
@@ -1396,28 +1308,34 @@ bool CMonitor::attemptDirectScanout() {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto explicitOptions = g_pHyprRenderer->getExplicitSyncSettings();
|
||||
|
||||
// wait for the explicit fence if present, and if kms explicit is allowed
|
||||
bool DOEXPLICIT = PSURFACE->syncobj && PSURFACE->syncobj->current.acquireTimeline && PSURFACE->syncobj->current.acquireTimeline->timeline && explicitOptions.explicitKMSEnabled;
|
||||
int explicitWaitFD = -1;
|
||||
if (DOEXPLICIT) {
|
||||
explicitWaitFD = PSURFACE->syncobj->current.acquireTimeline->timeline->exportAsSyncFileFD(PSURFACE->syncobj->current.acquirePoint);
|
||||
if (explicitWaitFD < 0)
|
||||
Debug::log(TRACE, "attemptDirectScanout: failed to acquire an explicit wait fd");
|
||||
}
|
||||
DOEXPLICIT = DOEXPLICIT && explicitWaitFD >= 0;
|
||||
|
||||
auto cleanup = CScopeGuard([explicitWaitFD, this]() {
|
||||
output->state->resetExplicitFences();
|
||||
if (explicitWaitFD >= 0)
|
||||
close(explicitWaitFD);
|
||||
});
|
||||
|
||||
timespec now;
|
||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||
PSURFACE->presentFeedback(&now, self.lock());
|
||||
|
||||
output->state->addDamage(PSURFACE->current.accumulateBufferDamage());
|
||||
output->state->addDamage(CBox{{}, vecPixelSize});
|
||||
output->state->resetExplicitFences();
|
||||
|
||||
auto cleanup = CScopeGuard([this]() { output->state->resetExplicitFences(); });
|
||||
|
||||
auto explicitOptions = g_pHyprRenderer->getExplicitSyncSettings(output);
|
||||
|
||||
bool DOEXPLICIT = PSURFACE->syncobj && PSURFACE->current.buffer && PSURFACE->current.buffer->acquire && explicitOptions.explicitKMSEnabled;
|
||||
if (DOEXPLICIT) {
|
||||
// wait for surface's explicit fence if present
|
||||
inFence = PSURFACE->current.buffer->acquire->exportAsFD();
|
||||
if (inFence.isValid()) {
|
||||
Debug::log(TRACE, "attemptDirectScanout: setting IN_FENCE for aq to {}", inFence.get());
|
||||
output->state->setExplicitInFence(inFence.get());
|
||||
} else {
|
||||
Debug::log(TRACE, "attemptDirectScanout: failed to acquire an sync file fd for aq IN_FENCE");
|
||||
DOEXPLICIT = false;
|
||||
}
|
||||
Debug::log(TRACE, "attemptDirectScanout: setting IN_FENCE for aq to {}", explicitWaitFD);
|
||||
output->state->setExplicitInFence(explicitWaitFD);
|
||||
}
|
||||
|
||||
bool ok = output->commit();
|
||||
@@ -1429,27 +1347,29 @@ bool CMonitor::attemptDirectScanout() {
|
||||
ok = output->commit();
|
||||
}
|
||||
|
||||
if (!ok) {
|
||||
if (ok) {
|
||||
if (lastScanout.expired()) {
|
||||
lastScanout = PCANDIDATE;
|
||||
Debug::log(LOG, "Entered a direct scanout to {:x}: \"{}\"", (uintptr_t)PCANDIDATE.get(), PCANDIDATE->m_szTitle);
|
||||
}
|
||||
|
||||
// delay explicit sync feedback until kms release of the buffer
|
||||
if (DOEXPLICIT) {
|
||||
Debug::log(TRACE, "attemptDirectScanout: Delaying explicit sync release feedback until kms release");
|
||||
PSURFACE->current.buffer->releaser->drop();
|
||||
|
||||
PSURFACE->current.buffer->buffer->hlEvents.backendRelease2 = PSURFACE->current.buffer->buffer->events.backendRelease.registerListener([PSURFACE](std::any d) {
|
||||
const bool DOEXPLICIT = PSURFACE->syncobj && PSURFACE->syncobj->current.releaseTimeline && PSURFACE->syncobj->current.releaseTimeline->timeline;
|
||||
if (DOEXPLICIT)
|
||||
PSURFACE->syncobj->current.releaseTimeline->timeline->signal(PSURFACE->syncobj->current.releasePoint);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
Debug::log(TRACE, "attemptDirectScanout: failed to scanout surface");
|
||||
lastScanout.reset();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (lastScanout.expired()) {
|
||||
lastScanout = PCANDIDATE;
|
||||
Debug::log(LOG, "Entered a direct scanout to {:x}: \"{}\"", (uintptr_t)PCANDIDATE.get(), PCANDIDATE->m_szTitle);
|
||||
}
|
||||
|
||||
scanoutNeedsCursorUpdate = false;
|
||||
|
||||
if (!PBUFFER->lockedByBackend || PBUFFER->hlEvents.backendRelease)
|
||||
return true;
|
||||
|
||||
// lock buffer while DRM/KMS is using it, then release it when page flip happens since DRM/KMS should be done by then
|
||||
// btw buffer's syncReleaser will take care of signaling release point, so we don't do that here
|
||||
PBUFFER->lock();
|
||||
PBUFFER->onBackendRelease([PBUFFER]() { PBUFFER->unlock(); });
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1521,25 +1441,11 @@ void CMonitor::onMonitorFrame() {
|
||||
g_pHyprRenderer->renderMonitor(self.lock());
|
||||
}
|
||||
|
||||
void CMonitor::onCursorMovedOnMonitor() {
|
||||
if (!tearingState.activelyTearing || !solitaryClient || !g_pHyprRenderer->shouldRenderCursor())
|
||||
return;
|
||||
|
||||
// submit a frame immediately. This will only update the cursor pos.
|
||||
// output->state->setBuffer(output->state->state().buffer);
|
||||
// output->state->addDamage(CRegion{});
|
||||
// output->state->setPresentationMode(Aquamarine::eOutputPresentationMode::AQ_OUTPUT_PRESENTATION_IMMEDIATE);
|
||||
// if (!output->commit())
|
||||
// Debug::log(ERR, "onCursorMovedOnMonitor: tearing and wanted to update cursor, failed.");
|
||||
|
||||
// FIXME: try to do the above. We currently can't just render because drm is a fucking bitch
|
||||
// and throws a "nO pRoP cAn Be ChAnGeD dUrInG AsYnC fLiP" on crtc_x
|
||||
// this will throw too but fix it if we use sw cursors
|
||||
|
||||
tearingState.frameScheduledWhileBusy = true;
|
||||
CMonitorState::CMonitorState(CMonitor* owner) : m_pOwner(owner) {
|
||||
;
|
||||
}
|
||||
|
||||
CMonitorState::CMonitorState(CMonitor* owner) : m_pOwner(owner) {
|
||||
CMonitorState::~CMonitorState() {
|
||||
;
|
||||
}
|
||||
|
||||
|
@@ -6,18 +6,17 @@
|
||||
#include "../SharedDefs.hpp"
|
||||
#include "MiscFunctions.hpp"
|
||||
#include "WLClasses.hpp"
|
||||
#include <vector>
|
||||
#include <array>
|
||||
|
||||
#include <xf86drmMode.h>
|
||||
#include "Timer.hpp"
|
||||
#include "math/Math.hpp"
|
||||
#include <optional>
|
||||
#include "../protocols/types/ColorManagement.hpp"
|
||||
#include "signal/Signal.hpp"
|
||||
#include "DamageRing.hpp"
|
||||
#include <aquamarine/output/Output.hpp>
|
||||
#include <aquamarine/allocator/Swapchain.hpp>
|
||||
#include <hyprutils/os/FileDescriptor.hpp>
|
||||
|
||||
// Enum for the different types of auto directions, e.g. auto-left, auto-up.
|
||||
enum eAutoDirs : uint8_t {
|
||||
@@ -28,41 +27,28 @@ enum eAutoDirs : uint8_t {
|
||||
DIR_AUTO_RIGHT
|
||||
};
|
||||
|
||||
enum eCMType : uint8_t {
|
||||
CM_AUTO = 0, // subject to change. srgb for 8bpc, wide for 10bpc if supported
|
||||
CM_SRGB, // default, sRGB primaries
|
||||
CM_WIDE, // wide color gamut, BT2020 primaries
|
||||
CM_EDID, // primaries from edid (known to be inaccurate)
|
||||
CM_HDR, // wide color gamut and HDR PQ transfer function
|
||||
CM_HDR_EDID, // same as CM_HDR with edid primaries
|
||||
};
|
||||
|
||||
struct SMonitorRule {
|
||||
eAutoDirs autoDir = DIR_AUTO_NONE;
|
||||
std::string name = "";
|
||||
Vector2D resolution = Vector2D(1280, 720);
|
||||
Vector2D offset = Vector2D(0, 0);
|
||||
float scale = 1;
|
||||
float refreshRate = 60; // Hz
|
||||
bool disabled = false;
|
||||
wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
||||
std::string mirrorOf = "";
|
||||
bool enable10bit = false;
|
||||
eCMType cmType = CM_SRGB;
|
||||
float sdrSaturation = 1.0f; // SDR -> HDR
|
||||
float sdrBrightness = 1.0f; // SDR -> HDR
|
||||
drmModeModeInfo drmMode = {};
|
||||
eAutoDirs autoDir = DIR_AUTO_NONE;
|
||||
std::string name = "";
|
||||
Vector2D resolution = Vector2D(1280, 720);
|
||||
Vector2D offset = Vector2D(0, 0);
|
||||
float scale = 1;
|
||||
float refreshRate = 60; // Hz
|
||||
bool disabled = false;
|
||||
wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
||||
std::string mirrorOf = "";
|
||||
bool enable10bit = false;
|
||||
drmModeModeInfo drmMode = {};
|
||||
std::optional<int> vrr;
|
||||
};
|
||||
|
||||
class CMonitor;
|
||||
class CSyncTimeline;
|
||||
class CEGLSync;
|
||||
|
||||
class CMonitorState {
|
||||
public:
|
||||
CMonitorState(CMonitor* owner);
|
||||
~CMonitorState() = default;
|
||||
~CMonitorState();
|
||||
|
||||
bool commit();
|
||||
bool test();
|
||||
@@ -121,9 +107,6 @@ class CMonitor {
|
||||
bool dpmsStatus = true;
|
||||
bool vrrActive = false; // this can be TRUE even if VRR is not active in the case that this display does not support it.
|
||||
bool enabled10bit = false; // as above, this can be TRUE even if 10 bit failed.
|
||||
eCMType cmType = CM_SRGB;
|
||||
float sdrSaturation = 1.0f;
|
||||
float sdrBrightness = 1.0f;
|
||||
bool createdByUser = false;
|
||||
bool isUnsafeFallback = false;
|
||||
|
||||
@@ -139,12 +122,11 @@ class CMonitor {
|
||||
SMonitorRule activeMonitorRule;
|
||||
|
||||
// explicit sync
|
||||
SP<CSyncTimeline> inTimeline;
|
||||
Hyprutils::OS::CFileDescriptor inFence;
|
||||
SP<CEGLSync> eglSync;
|
||||
uint64_t inTimelinePoint = 0;
|
||||
SP<CSyncTimeline> inTimeline;
|
||||
SP<CSyncTimeline> outTimeline;
|
||||
uint64_t commitSeq = 0;
|
||||
|
||||
PHLMONITORREF self;
|
||||
PHLMONITORREF self;
|
||||
|
||||
// mirroring
|
||||
PHLMONITORREF pMirrorOf;
|
||||
@@ -159,7 +141,6 @@ class CMonitor {
|
||||
|
||||
// for direct scanout
|
||||
PHLWINDOWREF lastScanout;
|
||||
bool scanoutNeedsCursorUpdate = false;
|
||||
|
||||
struct {
|
||||
bool canTear = false;
|
||||
@@ -181,39 +162,37 @@ class CMonitor {
|
||||
std::array<std::vector<PHLLSREF>, 4> m_aLayerSurfaceLayers;
|
||||
|
||||
// methods
|
||||
void onConnect(bool noRule);
|
||||
void onDisconnect(bool destroy = false);
|
||||
bool applyMonitorRule(SMonitorRule* pMonitorRule, bool force = false);
|
||||
void addDamage(const pixman_region32_t* rg);
|
||||
void addDamage(const CRegion& rg);
|
||||
void addDamage(const CBox& box);
|
||||
bool shouldSkipScheduleFrameOnMouseEvent();
|
||||
void setMirror(const std::string&);
|
||||
bool isMirror();
|
||||
bool matchesStaticSelector(const std::string& selector) const;
|
||||
float getDefaultScale();
|
||||
void changeWorkspace(const PHLWORKSPACE& pWorkspace, bool internal = false, bool noMouseMove = false, bool noFocus = false);
|
||||
void changeWorkspace(const WORKSPACEID& id, bool internal = false, bool noMouseMove = false, bool noFocus = false);
|
||||
void setSpecialWorkspace(const PHLWORKSPACE& pWorkspace);
|
||||
void setSpecialWorkspace(const WORKSPACEID& id);
|
||||
void moveTo(const Vector2D& pos);
|
||||
Vector2D middle();
|
||||
void updateMatrix();
|
||||
WORKSPACEID activeWorkspaceID();
|
||||
WORKSPACEID activeSpecialWorkspaceID();
|
||||
CBox logicalBox();
|
||||
void scheduleDone();
|
||||
bool attemptDirectScanout();
|
||||
void setCTM(const Mat3x3& ctm);
|
||||
void onCursorMovedOnMonitor();
|
||||
void onConnect(bool noRule);
|
||||
void onDisconnect(bool destroy = false);
|
||||
bool applyMonitorRule(SMonitorRule* pMonitorRule, bool force = false);
|
||||
void addDamage(const pixman_region32_t* rg);
|
||||
void addDamage(const CRegion& rg);
|
||||
void addDamage(const CBox& box);
|
||||
bool shouldSkipScheduleFrameOnMouseEvent();
|
||||
void setMirror(const std::string&);
|
||||
bool isMirror();
|
||||
bool matchesStaticSelector(const std::string& selector) const;
|
||||
float getDefaultScale();
|
||||
void changeWorkspace(const PHLWORKSPACE& pWorkspace, bool internal = false, bool noMouseMove = false, bool noFocus = false);
|
||||
void changeWorkspace(const WORKSPACEID& id, bool internal = false, bool noMouseMove = false, bool noFocus = false);
|
||||
void setSpecialWorkspace(const PHLWORKSPACE& pWorkspace);
|
||||
void setSpecialWorkspace(const WORKSPACEID& id);
|
||||
void moveTo(const Vector2D& pos);
|
||||
Vector2D middle();
|
||||
void updateMatrix();
|
||||
WORKSPACEID activeWorkspaceID();
|
||||
WORKSPACEID activeSpecialWorkspaceID();
|
||||
CBox logicalBox();
|
||||
void scheduleDone();
|
||||
bool attemptDirectScanout();
|
||||
void setCTM(const Mat3x3& ctm);
|
||||
|
||||
void debugLastPresentation(const std::string& message);
|
||||
void onMonitorFrame();
|
||||
void debugLastPresentation(const std::string& message);
|
||||
void onMonitorFrame();
|
||||
|
||||
bool m_bEnabled = false;
|
||||
bool m_bRenderingInitPassed = false;
|
||||
WP<CWindow> m_previousFSWindow;
|
||||
NColorManagement::SImageDescription imageDescription;
|
||||
bool m_bEnabled = false;
|
||||
bool m_bRenderingInitPassed = false;
|
||||
WP<CWindow> m_previousFSWindow;
|
||||
|
||||
// For the list lookup
|
||||
|
||||
|
@@ -58,7 +58,7 @@ namespace NSplashes {
|
||||
"Thanks ThatOneCalculator!",
|
||||
"The AUR packages always work, except for the times they don't.",
|
||||
"Funny animation compositor woo",
|
||||
"3 years!",
|
||||
"2 years!",
|
||||
// music reference / quote section
|
||||
"J'remue le ciel, le jour, la nuit.",
|
||||
"aezakmi, aezakmi, aezakmi, aezakmi, aezakmi, aezakmi, aezakmi!",
|
||||
|
@@ -1,65 +1,25 @@
|
||||
#include "SyncReleaser.hpp"
|
||||
#include "SyncTimeline.hpp"
|
||||
#include "../../render/OpenGL.hpp"
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#if defined(__linux__)
|
||||
#include <linux/sync_file.h>
|
||||
#else
|
||||
struct sync_merge_data {
|
||||
char name[32];
|
||||
__s32 fd2;
|
||||
__s32 fence;
|
||||
__u32 flags;
|
||||
__u32 pad;
|
||||
};
|
||||
#define SYNC_IOC_MAGIC '>'
|
||||
#define SYNC_IOC_MERGE _IOWR(SYNC_IOC_MAGIC, 3, struct sync_merge_data)
|
||||
#endif
|
||||
|
||||
using namespace Hyprutils::OS;
|
||||
|
||||
CSyncReleaser::CSyncReleaser(SP<CSyncTimeline> timeline, uint64_t point) : m_timeline(timeline), m_point(point) {
|
||||
CSyncReleaser::CSyncReleaser(WP<CSyncTimeline> timeline_, uint64_t point_) : timeline(timeline_), point(point_) {
|
||||
;
|
||||
}
|
||||
|
||||
CSyncReleaser::~CSyncReleaser() {
|
||||
if (!m_timeline) {
|
||||
Debug::log(ERR, "CSyncReleaser destructing without a timeline");
|
||||
if (timeline.expired())
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_fd.isValid())
|
||||
m_timeline->importFromSyncFileFD(m_point, m_fd);
|
||||
if (sync)
|
||||
timeline->importFromSyncFileFD(point, sync->fd());
|
||||
else
|
||||
m_timeline->signal(m_point);
|
||||
timeline->signal(point);
|
||||
}
|
||||
|
||||
CFileDescriptor CSyncReleaser::mergeSyncFds(const CFileDescriptor& fd1, const CFileDescriptor& fd2) {
|
||||
struct sync_merge_data data{
|
||||
.name = "merged release fence",
|
||||
.fd2 = fd2.get(),
|
||||
.fence = -1,
|
||||
};
|
||||
int err = -1;
|
||||
do {
|
||||
err = ioctl(fd1.get(), SYNC_IOC_MERGE, &data);
|
||||
} while (err == -1 && (errno == EINTR || errno == EAGAIN));
|
||||
if (err < 0)
|
||||
return CFileDescriptor{};
|
||||
else
|
||||
return CFileDescriptor(data.fence);
|
||||
}
|
||||
|
||||
void CSyncReleaser::addReleaseSync(SP<CEGLSync> sync) {
|
||||
if (m_fd.isValid())
|
||||
m_fd = mergeSyncFds(m_fd, sync->takeFD());
|
||||
else
|
||||
m_fd = sync->fd().duplicate();
|
||||
|
||||
m_sync = sync;
|
||||
void CSyncReleaser::addReleaseSync(SP<CEGLSync> sync_) {
|
||||
sync = sync_;
|
||||
}
|
||||
|
||||
void CSyncReleaser::drop() {
|
||||
m_timeline.reset();
|
||||
}
|
||||
timeline.reset();
|
||||
}
|
@@ -4,7 +4,6 @@
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
#include <hyprutils/os/FileDescriptor.hpp>
|
||||
#include "../memory/Memory.hpp"
|
||||
|
||||
/*
|
||||
@@ -16,19 +15,17 @@ class CEGLSync;
|
||||
|
||||
class CSyncReleaser {
|
||||
public:
|
||||
CSyncReleaser(SP<CSyncTimeline> timeline, uint64_t point);
|
||||
CSyncReleaser(WP<CSyncTimeline> timeline_, uint64_t point_);
|
||||
~CSyncReleaser();
|
||||
|
||||
// drops the releaser, will never signal anymore
|
||||
void drop();
|
||||
|
||||
// wait for this gpu job to finish before releasing
|
||||
Hyprutils::OS::CFileDescriptor mergeSyncFds(const Hyprutils::OS::CFileDescriptor& fd1, const Hyprutils::OS::CFileDescriptor& fd2);
|
||||
void addReleaseSync(SP<CEGLSync> sync);
|
||||
void addReleaseSync(SP<CEGLSync> sync);
|
||||
|
||||
private:
|
||||
SP<CSyncTimeline> m_timeline;
|
||||
uint64_t m_point = 0;
|
||||
Hyprutils::OS::CFileDescriptor m_fd;
|
||||
SP<CEGLSync> m_sync;
|
||||
WP<CSyncTimeline> timeline;
|
||||
uint64_t point = 0;
|
||||
SP<CEGLSync> sync;
|
||||
};
|
||||
|
@@ -4,7 +4,6 @@
|
||||
|
||||
#include <xf86drm.h>
|
||||
#include <sys/eventfd.h>
|
||||
using namespace Hyprutils::OS;
|
||||
|
||||
SP<CSyncTimeline> CSyncTimeline::create(int drmFD_) {
|
||||
auto timeline = SP<CSyncTimeline>(new CSyncTimeline);
|
||||
@@ -19,13 +18,12 @@ SP<CSyncTimeline> CSyncTimeline::create(int drmFD_) {
|
||||
return timeline;
|
||||
}
|
||||
|
||||
SP<CSyncTimeline> CSyncTimeline::create(int drmFD_, CFileDescriptor&& drmSyncobjFD) {
|
||||
auto timeline = SP<CSyncTimeline>(new CSyncTimeline);
|
||||
timeline->drmFD = drmFD_;
|
||||
timeline->syncobjFd = std::move(drmSyncobjFD);
|
||||
timeline->self = timeline;
|
||||
SP<CSyncTimeline> CSyncTimeline::create(int drmFD_, int drmSyncobjFD) {
|
||||
auto timeline = SP<CSyncTimeline>(new CSyncTimeline);
|
||||
timeline->drmFD = drmFD_;
|
||||
timeline->self = timeline;
|
||||
|
||||
if (drmSyncobjFDToHandle(drmFD_, timeline->syncobjFd.get(), &timeline->handle)) {
|
||||
if (drmSyncobjFDToHandle(drmFD_, drmSyncobjFD, &timeline->handle)) {
|
||||
Debug::log(ERR, "CSyncTimeline: failed to create a drm syncobj from fd??");
|
||||
return nullptr;
|
||||
}
|
||||
@@ -34,13 +32,6 @@ SP<CSyncTimeline> CSyncTimeline::create(int drmFD_, CFileDescriptor&& drmSyncobj
|
||||
}
|
||||
|
||||
CSyncTimeline::~CSyncTimeline() {
|
||||
for (auto& w : waiters) {
|
||||
if (w->source) {
|
||||
wl_event_source_remove(w->source);
|
||||
w->source = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (handle == 0)
|
||||
return;
|
||||
|
||||
@@ -94,9 +85,10 @@ bool CSyncTimeline::addWaiter(const std::function<void()>& waiter, uint64_t poin
|
||||
auto w = makeShared<SWaiter>();
|
||||
w->fn = waiter;
|
||||
w->timeline = self;
|
||||
w->eventFd = CFileDescriptor{eventfd(0, EFD_CLOEXEC)};
|
||||
|
||||
if (!w->eventFd.isValid()) {
|
||||
int eventFD = eventfd(0, EFD_CLOEXEC);
|
||||
|
||||
if (eventFD < 0) {
|
||||
Debug::log(ERR, "CSyncTimeline::addWaiter: failed to acquire an eventfd");
|
||||
return false;
|
||||
}
|
||||
@@ -105,17 +97,19 @@ bool CSyncTimeline::addWaiter(const std::function<void()>& waiter, uint64_t poin
|
||||
.handle = handle,
|
||||
.flags = flags,
|
||||
.point = point,
|
||||
.fd = w->eventFd.get(),
|
||||
.fd = eventFD,
|
||||
};
|
||||
|
||||
if (drmIoctl(drmFD, DRM_IOCTL_SYNCOBJ_EVENTFD, &syncobjEventFD) != 0) {
|
||||
Debug::log(ERR, "CSyncTimeline::addWaiter: drmIoctl failed");
|
||||
close(eventFD);
|
||||
return false;
|
||||
}
|
||||
|
||||
w->source = wl_event_loop_add_fd(g_pEventLoopManager->m_sWayland.loop, w->eventFd.get(), WL_EVENT_READABLE, ::handleWaiterFD, w.get());
|
||||
w->source = wl_event_loop_add_fd(g_pEventLoopManager->m_sWayland.loop, eventFD, WL_EVENT_READABLE, ::handleWaiterFD, w.get());
|
||||
if (!w->source) {
|
||||
Debug::log(ERR, "CSyncTimeline::addWaiter: wl_event_loop_add_fd failed");
|
||||
close(eventFD);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -132,43 +126,32 @@ void CSyncTimeline::removeWaiter(SWaiter* w) {
|
||||
std::erase_if(waiters, [w](const auto& e) { return e.get() == w; });
|
||||
}
|
||||
|
||||
void CSyncTimeline::removeAllWaiters() {
|
||||
for (auto& w : waiters) {
|
||||
if (w->source) {
|
||||
wl_event_source_remove(w->source);
|
||||
w->source = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
waiters.clear();
|
||||
}
|
||||
|
||||
CFileDescriptor CSyncTimeline::exportAsSyncFileFD(uint64_t src) {
|
||||
int CSyncTimeline::exportAsSyncFileFD(uint64_t src) {
|
||||
int sync = -1;
|
||||
|
||||
uint32_t syncHandle = 0;
|
||||
if (drmSyncobjCreate(drmFD, 0, &syncHandle)) {
|
||||
Debug::log(ERR, "exportAsSyncFileFD: drmSyncobjCreate failed");
|
||||
return {};
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (drmSyncobjTransfer(drmFD, syncHandle, 0, handle, src, 0)) {
|
||||
Debug::log(ERR, "exportAsSyncFileFD: drmSyncobjTransfer failed");
|
||||
drmSyncobjDestroy(drmFD, syncHandle);
|
||||
return {};
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (drmSyncobjExportSyncFile(drmFD, syncHandle, &sync)) {
|
||||
Debug::log(ERR, "exportAsSyncFileFD: drmSyncobjExportSyncFile failed");
|
||||
drmSyncobjDestroy(drmFD, syncHandle);
|
||||
return {};
|
||||
return -1;
|
||||
}
|
||||
|
||||
drmSyncobjDestroy(drmFD, syncHandle);
|
||||
return CFileDescriptor{sync};
|
||||
return sync;
|
||||
}
|
||||
|
||||
bool CSyncTimeline::importFromSyncFileFD(uint64_t dst, CFileDescriptor& fd) {
|
||||
bool CSyncTimeline::importFromSyncFileFD(uint64_t dst, int fd) {
|
||||
uint32_t syncHandle = 0;
|
||||
|
||||
if (drmSyncobjCreate(drmFD, 0, &syncHandle)) {
|
||||
@@ -176,7 +159,7 @@ bool CSyncTimeline::importFromSyncFileFD(uint64_t dst, CFileDescriptor& fd) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (drmSyncobjImportSyncFile(drmFD, syncHandle, fd.get())) {
|
||||
if (drmSyncobjImportSyncFile(drmFD, syncHandle, fd)) {
|
||||
Debug::log(ERR, "importFromSyncFileFD: drmSyncobjImportSyncFile failed");
|
||||
drmSyncobjDestroy(drmFD, syncHandle);
|
||||
return false;
|
||||
|
@@ -4,7 +4,6 @@
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
#include <hyprutils/os/FileDescriptor.hpp>
|
||||
#include "../memory/Memory.hpp"
|
||||
|
||||
/*
|
||||
@@ -17,33 +16,30 @@ struct wl_event_source;
|
||||
class CSyncTimeline {
|
||||
public:
|
||||
static SP<CSyncTimeline> create(int drmFD_);
|
||||
static SP<CSyncTimeline> create(int drmFD_, Hyprutils::OS::CFileDescriptor&& drmSyncobjFD);
|
||||
static SP<CSyncTimeline> create(int drmFD_, int drmSyncobjFD);
|
||||
~CSyncTimeline();
|
||||
|
||||
struct SWaiter {
|
||||
std::function<void()> fn;
|
||||
wl_event_source* source = nullptr;
|
||||
WP<CSyncTimeline> timeline;
|
||||
Hyprutils::OS::CFileDescriptor eventFd;
|
||||
std::function<void()> fn;
|
||||
wl_event_source* source = nullptr;
|
||||
WP<CSyncTimeline> timeline;
|
||||
};
|
||||
|
||||
// check if the timeline point has been signaled
|
||||
// flags: DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT or DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE
|
||||
// std::nullopt on fail
|
||||
std::optional<bool> check(uint64_t point, uint32_t flags);
|
||||
std::optional<bool> check(uint64_t point, uint32_t flags);
|
||||
|
||||
bool addWaiter(const std::function<void()>& waiter, uint64_t point, uint32_t flags);
|
||||
void removeWaiter(SWaiter*);
|
||||
void removeAllWaiters();
|
||||
Hyprutils::OS::CFileDescriptor exportAsSyncFileFD(uint64_t src);
|
||||
bool importFromSyncFileFD(uint64_t dst, Hyprutils::OS::CFileDescriptor& fd);
|
||||
bool transfer(SP<CSyncTimeline> from, uint64_t fromPoint, uint64_t toPoint);
|
||||
void signal(uint64_t point);
|
||||
bool addWaiter(const std::function<void()>& waiter, uint64_t point, uint32_t flags);
|
||||
void removeWaiter(SWaiter*);
|
||||
int exportAsSyncFileFD(uint64_t src);
|
||||
bool importFromSyncFileFD(uint64_t dst, int fd);
|
||||
bool transfer(SP<CSyncTimeline> from, uint64_t fromPoint, uint64_t toPoint);
|
||||
void signal(uint64_t point);
|
||||
|
||||
int drmFD = -1;
|
||||
Hyprutils::OS::CFileDescriptor syncobjFd;
|
||||
uint32_t handle = 0;
|
||||
WP<CSyncTimeline> self;
|
||||
int drmFD = -1;
|
||||
uint32_t handle = 0;
|
||||
WP<CSyncTimeline> self;
|
||||
|
||||
private:
|
||||
CSyncTimeline() = default;
|
||||
|
@@ -32,6 +32,8 @@ CHyprError::CHyprError() {
|
||||
m_pTexture = makeShared<CTexture>();
|
||||
}
|
||||
|
||||
CHyprError::~CHyprError() = default;
|
||||
|
||||
void CHyprError::queueCreate(std::string message, const CHyprColor& color) {
|
||||
m_szQueued = message;
|
||||
m_cQueued = color;
|
||||
|
@@ -9,7 +9,7 @@
|
||||
class CHyprError {
|
||||
public:
|
||||
CHyprError();
|
||||
~CHyprError() = default;
|
||||
~CHyprError();
|
||||
|
||||
void queueCreate(std::string message, const CHyprColor& color);
|
||||
void draw();
|
||||
|
@@ -198,12 +198,16 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for
|
||||
|
||||
*PWINDOW->m_vRealPosition = wb.pos();
|
||||
*PWINDOW->m_vRealSize = wb.size();
|
||||
|
||||
PWINDOW->sendWindowSize(wb.size());
|
||||
} else {
|
||||
CBox wb = {calcPos, calcSize};
|
||||
wb.round(); // avoid rounding mess
|
||||
|
||||
*PWINDOW->m_vRealSize = wb.size();
|
||||
*PWINDOW->m_vRealPosition = wb.pos();
|
||||
|
||||
PWINDOW->sendWindowSize(wb.size());
|
||||
}
|
||||
|
||||
if (force) {
|
||||
|
@@ -14,17 +14,9 @@
|
||||
#include "../managers/HookSystemManager.hpp"
|
||||
|
||||
void IHyprLayout::onWindowCreated(PHLWINDOW pWindow, eDirection direction) {
|
||||
CBox desiredGeometry = g_pXWaylandManager->getGeometryForWindow(pWindow);
|
||||
CBox desiredGeometry = g_pXWaylandManager->getGeometryForWindow(pWindow);
|
||||
|
||||
const bool HASPERSISTENTSIZE =
|
||||
std::any_of(pWindow->m_vMatchedRules.begin(), pWindow->m_vMatchedRules.end(), [](const auto& rule) { return rule->ruleType == CWindowRule::RULE_PERSISTENTSIZE; });
|
||||
|
||||
const auto STOREDSIZE = HASPERSISTENTSIZE ? g_pConfigManager->getStoredFloatingSize(pWindow) : std::nullopt;
|
||||
|
||||
if (STOREDSIZE.has_value()) {
|
||||
Debug::log(LOG, "using stored size {}x{} for new window {}::{}", STOREDSIZE->x, STOREDSIZE->y, pWindow->m_szClass, pWindow->m_szTitle);
|
||||
pWindow->m_vLastFloatingSize = STOREDSIZE.value();
|
||||
} else if (desiredGeometry.width <= 5 || desiredGeometry.height <= 5) {
|
||||
if (desiredGeometry.width <= 5 || desiredGeometry.height <= 5) {
|
||||
const auto PMONITOR = pWindow->m_pMonitor.lock();
|
||||
pWindow->m_vLastFloatingSize = PMONITOR->vecSize / 2.f;
|
||||
} else
|
||||
@@ -184,9 +176,11 @@ void IHyprLayout::onWindowCreatedFloating(PHLWINDOW pWindow) {
|
||||
pWindow->m_vRealSize->warp();
|
||||
}
|
||||
|
||||
if (!pWindow->isX11OverrideRedirect())
|
||||
if (!pWindow->isX11OverrideRedirect()) {
|
||||
pWindow->sendWindowSize(pWindow->m_vRealSize->goal());
|
||||
|
||||
g_pCompositor->changeWindowZOrder(pWindow, true);
|
||||
else {
|
||||
} else {
|
||||
pWindow->m_vPendingReportedSize = pWindow->m_vRealSize->goal();
|
||||
pWindow->m_vReportedSize = pWindow->m_vPendingReportedSize;
|
||||
}
|
||||
@@ -313,7 +307,7 @@ void IHyprLayout::onBeginDragWindow() {
|
||||
}
|
||||
|
||||
if (g_pInputManager->dragMode != MBIND_RESIZE && g_pInputManager->dragMode != MBIND_RESIZE_FORCE_RATIO && g_pInputManager->dragMode != MBIND_RESIZE_BLOCK_RATIO)
|
||||
g_pInputManager->setCursorImageUntilUnset("grabbing");
|
||||
g_pInputManager->setCursorImageUntilUnset("grab");
|
||||
|
||||
g_pHyprRenderer->damageWindow(DRAGGINGWINDOW);
|
||||
|
||||
@@ -368,6 +362,9 @@ void IHyprLayout::onEndDragWindow() {
|
||||
DRAGGINGWINDOW->m_vLastFloatingSize = m_vDraggingWindowOriginalFloatSize;
|
||||
DRAGGINGWINDOW->m_bDraggingTiled = false;
|
||||
|
||||
if (pWindow->m_bIsFloating)
|
||||
DRAGGINGWINDOW->sendWindowSize(DRAGGINGWINDOW->m_vRealSize->goal()); // match the size of the window
|
||||
|
||||
static auto USECURRPOS = CConfigValue<Hyprlang::INT>("group:insert_after_current");
|
||||
(*USECURRPOS ? pWindow : pWindow->getGroupTail())->insertWindowToGroup(DRAGGINGWINDOW);
|
||||
pWindow->setGroupCurrent(DRAGGINGWINDOW);
|
||||
@@ -609,11 +606,10 @@ void IHyprLayout::onMouseMove(const Vector2D& mousePos) {
|
||||
|
||||
if (*PANIMATEMOUSE)
|
||||
*DRAGGINGWINDOW->m_vRealPosition = wb.pos();
|
||||
else {
|
||||
else
|
||||
DRAGGINGWINDOW->m_vRealPosition->setValueAndWarp(wb.pos());
|
||||
DRAGGINGWINDOW->sendWindowSize();
|
||||
}
|
||||
|
||||
DRAGGINGWINDOW->sendWindowSize(DRAGGINGWINDOW->m_vRealSize->goal());
|
||||
} 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) {
|
||||
|
||||
@@ -683,8 +679,9 @@ void IHyprLayout::onMouseMove(const Vector2D& mousePos) {
|
||||
} else {
|
||||
DRAGGINGWINDOW->m_vRealSize->setValueAndWarp(wb.size());
|
||||
DRAGGINGWINDOW->m_vRealPosition->setValueAndWarp(wb.pos());
|
||||
DRAGGINGWINDOW->sendWindowSize();
|
||||
}
|
||||
|
||||
DRAGGINGWINDOW->sendWindowSize(DRAGGINGWINDOW->m_vRealSize->goal());
|
||||
} else {
|
||||
resizeActiveWindow(TICKDELTA, m_eGrabbedCorner, DRAGGINGWINDOW);
|
||||
}
|
||||
@@ -790,6 +787,7 @@ void IHyprLayout::changeWindowFloatingMode(PHLWINDOW pWindow) {
|
||||
|
||||
g_pCompositor->updateWindowAnimatedDecorationValues(pWindow);
|
||||
pWindow->updateToplevel();
|
||||
pWindow->sendWindowSize(pWindow->m_vRealSize->goal());
|
||||
g_pHyprRenderer->damageWindow(pWindow);
|
||||
}
|
||||
|
||||
@@ -952,3 +950,5 @@ Vector2D IHyprLayout::predictSizeForNewWindow(PHLWINDOW pWindow) {
|
||||
|
||||
return sizePredicted;
|
||||
}
|
||||
|
||||
IHyprLayout::~IHyprLayout() = default;
|
||||
|
@@ -43,7 +43,7 @@ enum eDirection : int8_t {
|
||||
|
||||
class IHyprLayout {
|
||||
public:
|
||||
virtual ~IHyprLayout() = default;
|
||||
virtual ~IHyprLayout() = 0;
|
||||
virtual void onEnable() = 0;
|
||||
virtual void onDisable() = 0;
|
||||
|
||||
|
@@ -374,22 +374,8 @@ void CHyprMasterLayout::calculateWorkspace(PHLWORKSPACE pWorkspace) {
|
||||
|
||||
// compute placement of master window(s)
|
||||
if (WINDOWS == 1 && !centerMasterWindow) {
|
||||
static auto PALWAYSKEEPPOSITION = CConfigValue<Hyprlang::INT>("master:always_keep_position");
|
||||
if (*PALWAYSKEEPPOSITION) {
|
||||
const float WIDTH = WSSIZE.x * PMASTERNODE->percMaster;
|
||||
float nextX = 0;
|
||||
|
||||
if (orientation == ORIENTATION_RIGHT)
|
||||
nextX = WSSIZE.x - WIDTH;
|
||||
else if (orientation == ORIENTATION_CENTER)
|
||||
nextX = (WSSIZE.x - WIDTH) / 2;
|
||||
|
||||
PMASTERNODE->size = Vector2D(WIDTH, WSSIZE.y);
|
||||
PMASTERNODE->position = WSPOS + Vector2D((double)nextX, 0.0);
|
||||
} else {
|
||||
PMASTERNODE->size = WSSIZE;
|
||||
PMASTERNODE->position = WSPOS;
|
||||
}
|
||||
PMASTERNODE->size = WSSIZE;
|
||||
PMASTERNODE->position = WSPOS;
|
||||
|
||||
applyNodeDataToWindow(PMASTERNODE);
|
||||
return;
|
||||
@@ -692,12 +678,16 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) {
|
||||
|
||||
*PWINDOW->m_vRealPosition = wb.pos();
|
||||
*PWINDOW->m_vRealSize = wb.size();
|
||||
|
||||
PWINDOW->sendWindowSize(wb.size());
|
||||
} else {
|
||||
CBox wb = {calcPos, calcSize};
|
||||
wb.round(); // avoid rounding mess
|
||||
|
||||
*PWINDOW->m_vRealPosition = wb.pos();
|
||||
*PWINDOW->m_vRealSize = wb.size();
|
||||
|
||||
PWINDOW->sendWindowSize(wb.size());
|
||||
}
|
||||
|
||||
if (m_bForceWarps && !*PANIMATE) {
|
||||
@@ -1367,7 +1357,7 @@ void CHyprMasterLayout::runOrientationCycle(SLayoutMessageHeader& header, CVarLi
|
||||
|
||||
int nextOrPrev = 0;
|
||||
for (size_t i = 0; i < cycle.size(); ++i) {
|
||||
if (PWORKSPACEDATA->orientation == cycle[i]) {
|
||||
if (PWORKSPACEDATA->orientation == cycle.at(i)) {
|
||||
nextOrPrev = i + direction;
|
||||
break;
|
||||
}
|
||||
|
@@ -5,6 +5,7 @@
|
||||
#include "../helpers/varlist/VarList.hpp"
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <vector>
|
||||
#include <any>
|
||||
|
||||
enum eFullscreenMode : int8_t;
|
||||
|
@@ -38,8 +38,7 @@
|
||||
#define DYNLISTENER(name) CHyprWLListener hyprListener_##name
|
||||
#define DYNMULTILISTENER(name) wl_listener listen_##name
|
||||
|
||||
#define VECINRECT(vec, x1, y1, x2, y2) ((vec).x >= (x1) && (vec).x < (x2) && (vec).y >= (y1) && (vec).y < (y2))
|
||||
#define VECNOTINRECT(vec, x1, y1, x2, y2) ((vec).x < (x1) || (vec).x >= (x2) || (vec).y < (y1) || (vec).y >= (y2))
|
||||
#define VECINRECT(vec, x1, y1, x2, y2) ((vec).x >= (x1) && (vec).x < (x2) && (vec).y >= (y1) && (vec).y < (y2))
|
||||
|
||||
#define DELTALESSTHAN(a, b, delta) (abs((a) - (b)) < (delta))
|
||||
|
||||
@@ -89,7 +88,6 @@
|
||||
{ \
|
||||
Debug::log(CRIT, "\n\nMEMORY CORRUPTED: Unreachable failed! (Reached an unreachable position, memory corruption!!!)"); \
|
||||
raise(SIGABRT); \
|
||||
std::unreachable(); \
|
||||
}
|
||||
#else
|
||||
#define UNREACHABLE() std::unreachable();
|
||||
@@ -112,7 +110,6 @@
|
||||
} \
|
||||
}
|
||||
|
||||
#define AQUAMARINE_VERSION_NUMBER (AQUAMARINE_VERSION_MAJOR * 10000 + AQUAMARINE_VERSION_MINOR * 100 + AQUAMARINE_VERSION_PATCH)
|
||||
#define AQUAMARINE_FORWARD(name) \
|
||||
namespace Aquamarine { \
|
||||
class name; \
|
||||
|
@@ -43,7 +43,6 @@ int main(int argc, char** argv) {
|
||||
|
||||
setenv("HYPRLAND_CMD", cmd.c_str(), 1);
|
||||
setenv("XDG_BACKEND", "wayland", 1);
|
||||
setenv("XDG_SESSION_TYPE", "wayland", 1);
|
||||
setenv("_JAVA_AWT_WM_NONREPARENTING", "1", 1);
|
||||
setenv("MOZ_ENABLE_WAYLAND", "1", 1);
|
||||
|
||||
|
@@ -1,251 +0,0 @@
|
||||
#include "ANRManager.hpp"
|
||||
#include "../helpers/fs/FsUtils.hpp"
|
||||
#include "../debug/Log.hpp"
|
||||
#include "../macros.hpp"
|
||||
#include "HookSystemManager.hpp"
|
||||
#include "../Compositor.hpp"
|
||||
#include "../protocols/XDGShell.hpp"
|
||||
#include "./eventLoop/EventLoopManager.hpp"
|
||||
#include "../config/ConfigValue.hpp"
|
||||
#include "../xwayland/XSurface.hpp"
|
||||
|
||||
using namespace Hyprutils::OS;
|
||||
|
||||
static constexpr auto TIMER_TIMEOUT = std::chrono::milliseconds(1500);
|
||||
|
||||
CANRManager::CANRManager() {
|
||||
if (!NFsUtils::executableExistsInPath("hyprland-dialog")) {
|
||||
Debug::log(ERR, "hyprland-dialog missing from PATH, cannot start ANRManager");
|
||||
return;
|
||||
}
|
||||
|
||||
m_timer = makeShared<CEventLoopTimer>(TIMER_TIMEOUT, [this](SP<CEventLoopTimer> self, void* data) { onTick(); }, this);
|
||||
g_pEventLoopManager->addTimer(m_timer);
|
||||
|
||||
m_active = true;
|
||||
|
||||
static auto P = g_pHookSystem->hookDynamic("openWindow", [this](void* self, SCallbackInfo& info, std::any data) {
|
||||
auto window = std::any_cast<PHLWINDOW>(data);
|
||||
|
||||
for (const auto& d : m_data) {
|
||||
if (d->fitsWindow(window))
|
||||
return;
|
||||
}
|
||||
|
||||
m_data.emplace_back(makeShared<SANRData>(window));
|
||||
});
|
||||
|
||||
m_timer->updateTimeout(TIMER_TIMEOUT);
|
||||
}
|
||||
|
||||
void CANRManager::onTick() {
|
||||
std::erase_if(m_data, [](const auto& e) { return e->isDefunct(); });
|
||||
|
||||
static auto PENABLEANR = CConfigValue<Hyprlang::INT>("misc:enable_anr_dialog");
|
||||
|
||||
if (!*PENABLEANR) {
|
||||
m_timer->updateTimeout(TIMER_TIMEOUT * 10);
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto& data : m_data) {
|
||||
PHLWINDOW firstWindow;
|
||||
int count = 0;
|
||||
for (const auto& w : g_pCompositor->m_vWindows) {
|
||||
if (!w->m_bIsMapped)
|
||||
continue;
|
||||
|
||||
if (!data->fitsWindow(w))
|
||||
continue;
|
||||
|
||||
count++;
|
||||
if (!firstWindow)
|
||||
firstWindow = w;
|
||||
}
|
||||
|
||||
if (count == 0)
|
||||
continue;
|
||||
|
||||
if (data->missedResponses > 0) {
|
||||
if (!data->isThreadRunning() && !data->dialogThreadSaidWait) {
|
||||
data->runDialog("Application Not Responding", firstWindow->m_szTitle, firstWindow->m_szClass, data->getPid());
|
||||
|
||||
for (const auto& w : g_pCompositor->m_vWindows) {
|
||||
if (!w->m_bIsMapped)
|
||||
continue;
|
||||
|
||||
if (!data->fitsWindow(w))
|
||||
continue;
|
||||
|
||||
*w->m_notRespondingTint = 0.2F;
|
||||
}
|
||||
}
|
||||
} else if (data->isThreadRunning())
|
||||
data->killDialog();
|
||||
|
||||
if (data->missedResponses == 0)
|
||||
data->dialogThreadSaidWait = false;
|
||||
|
||||
data->missedResponses++;
|
||||
|
||||
data->ping();
|
||||
}
|
||||
|
||||
m_timer->updateTimeout(TIMER_TIMEOUT);
|
||||
}
|
||||
|
||||
void CANRManager::onResponse(SP<CXDGWMBase> wmBase) {
|
||||
const auto DATA = dataFor(wmBase);
|
||||
|
||||
if (!DATA)
|
||||
return;
|
||||
|
||||
onResponse(DATA);
|
||||
}
|
||||
|
||||
void CANRManager::onResponse(SP<CXWaylandSurface> pXwaylandSurface) {
|
||||
const auto DATA = dataFor(pXwaylandSurface);
|
||||
|
||||
if (!DATA)
|
||||
return;
|
||||
|
||||
onResponse(DATA);
|
||||
}
|
||||
|
||||
void CANRManager::onResponse(SP<CANRManager::SANRData> data) {
|
||||
data->missedResponses = 0;
|
||||
if (data->isThreadRunning())
|
||||
data->killDialog();
|
||||
}
|
||||
|
||||
bool CANRManager::isNotResponding(PHLWINDOW pWindow) {
|
||||
const auto DATA = dataFor(pWindow);
|
||||
|
||||
if (!DATA)
|
||||
return false;
|
||||
|
||||
return isNotResponding(DATA);
|
||||
}
|
||||
|
||||
bool CANRManager::isNotResponding(SP<CANRManager::SANRData> data) {
|
||||
return data->missedResponses > 1;
|
||||
}
|
||||
|
||||
SP<CANRManager::SANRData> CANRManager::dataFor(PHLWINDOW pWindow) {
|
||||
auto it = m_data.end();
|
||||
if (pWindow->m_pXWaylandSurface)
|
||||
it = std::ranges::find_if(m_data, [&pWindow](const auto& data) { return data->xwaylandSurface && data->xwaylandSurface == pWindow->m_pXWaylandSurface; });
|
||||
else if (pWindow->m_pXDGSurface)
|
||||
it = std::ranges::find_if(m_data, [&pWindow](const auto& data) { return data->xdgBase && data->xdgBase == pWindow->m_pXDGSurface->owner; });
|
||||
return it == m_data.end() ? nullptr : *it;
|
||||
}
|
||||
|
||||
SP<CANRManager::SANRData> CANRManager::dataFor(SP<CXDGWMBase> wmBase) {
|
||||
auto it = std::ranges::find_if(m_data, [&wmBase](const auto& data) { return data->xdgBase && data->xdgBase == wmBase; });
|
||||
return it == m_data.end() ? nullptr : *it;
|
||||
}
|
||||
|
||||
SP<CANRManager::SANRData> CANRManager::dataFor(SP<CXWaylandSurface> pXwaylandSurface) {
|
||||
auto it = std::ranges::find_if(m_data, [&pXwaylandSurface](const auto& data) { return data->xwaylandSurface && data->xwaylandSurface == pXwaylandSurface; });
|
||||
return it == m_data.end() ? nullptr : *it;
|
||||
}
|
||||
|
||||
CANRManager::SANRData::SANRData(PHLWINDOW pWindow) :
|
||||
xwaylandSurface(pWindow->m_pXWaylandSurface), xdgBase(pWindow->m_pXDGSurface ? pWindow->m_pXDGSurface->owner : WP<CXDGWMBase>{}) {
|
||||
;
|
||||
}
|
||||
|
||||
CANRManager::SANRData::~SANRData() {
|
||||
if (dialogThread.joinable()) {
|
||||
killDialog();
|
||||
// dangerous: might lock if the above failed!!
|
||||
dialogThread.join();
|
||||
}
|
||||
}
|
||||
|
||||
void CANRManager::SANRData::runDialog(const std::string& title, const std::string& appName, const std::string appClass, pid_t dialogWmPID) {
|
||||
if (!dialogThreadExited)
|
||||
killDialog();
|
||||
|
||||
// dangerous: might lock if the above failed!!
|
||||
if (dialogThread.joinable())
|
||||
dialogThread.join();
|
||||
|
||||
dialogThreadExited = false;
|
||||
dialogThreadSaidWait = false;
|
||||
dialogThread = std::thread([title, appName, appClass, dialogWmPID, this]() {
|
||||
SP<CProcess> proc = makeShared<CProcess>("hyprland-dialog",
|
||||
std::vector<std::string>{"--title", title, "--text",
|
||||
std::format("Application {} with class of {} is not responding.\nWhat do you want to do with it?",
|
||||
appName.empty() ? "unknown" : appName, appClass.empty() ? "unknown" : appClass),
|
||||
"--buttons", "Terminate;Wait"});
|
||||
|
||||
dialogProc = proc;
|
||||
proc->runSync();
|
||||
|
||||
dialogThreadExited = true;
|
||||
|
||||
if (proc->stdOut().empty())
|
||||
return;
|
||||
|
||||
if (proc->stdOut().starts_with("Terminate"))
|
||||
kill(dialogWmPID, SIGKILL);
|
||||
if (proc->stdOut().starts_with("Wait"))
|
||||
dialogThreadSaidWait = true;
|
||||
});
|
||||
}
|
||||
|
||||
bool CANRManager::SANRData::isThreadRunning() {
|
||||
if (dialogThread.native_handle() == 0)
|
||||
return false;
|
||||
if (dialogThreadExited)
|
||||
return false;
|
||||
return pthread_kill(dialogThread.native_handle(), 0) != ESRCH;
|
||||
}
|
||||
|
||||
void CANRManager::SANRData::killDialog() const {
|
||||
if (!dialogProc)
|
||||
return;
|
||||
|
||||
if (!dialogProc->pid()) {
|
||||
Debug::log(ERR, "ANR: cannot kill dialogProc, as it doesn't have a pid. If you have hyprutils <= 0.6.0, you will crash soon. Otherwise, dialog failed to spawn??");
|
||||
return;
|
||||
}
|
||||
|
||||
kill(dialogProc->pid(), SIGKILL);
|
||||
}
|
||||
|
||||
bool CANRManager::SANRData::fitsWindow(PHLWINDOW pWindow) const {
|
||||
if (pWindow->m_pXWaylandSurface)
|
||||
return pWindow->m_pXWaylandSurface == xwaylandSurface;
|
||||
else if (pWindow->m_pXDGSurface)
|
||||
return pWindow->m_pXDGSurface->owner == xdgBase && xdgBase;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CANRManager::SANRData::isDefunct() const {
|
||||
return xdgBase.expired() && xwaylandSurface.expired();
|
||||
}
|
||||
|
||||
pid_t CANRManager::SANRData::getPid() const {
|
||||
if (xdgBase) {
|
||||
pid_t pid = 0;
|
||||
wl_client_get_credentials(xdgBase->client(), &pid, nullptr, nullptr);
|
||||
return pid;
|
||||
}
|
||||
|
||||
if (xwaylandSurface)
|
||||
return xwaylandSurface->pid;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CANRManager::SANRData::ping() {
|
||||
if (xdgBase) {
|
||||
xdgBase->ping();
|
||||
return;
|
||||
}
|
||||
|
||||
if (xwaylandSurface)
|
||||
xwaylandSurface->ping();
|
||||
}
|
@@ -1,62 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "../helpers/memory/Memory.hpp"
|
||||
#include "../desktop/DesktopTypes.hpp"
|
||||
#include <chrono>
|
||||
#include <hyprutils/os/Process.hpp>
|
||||
#include <hyprutils/os/FileDescriptor.hpp>
|
||||
#include "./eventLoop/EventLoopTimer.hpp"
|
||||
#include "../helpers/signal/Signal.hpp"
|
||||
#include <atomic>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
class CXDGWMBase;
|
||||
class CXWaylandSurface;
|
||||
|
||||
class CANRManager {
|
||||
public:
|
||||
CANRManager();
|
||||
|
||||
void onResponse(SP<CXDGWMBase> wmBase);
|
||||
void onResponse(SP<CXWaylandSurface> xwaylandSurface);
|
||||
bool isNotResponding(PHLWINDOW pWindow);
|
||||
|
||||
private:
|
||||
bool m_active = false;
|
||||
SP<CEventLoopTimer> m_timer;
|
||||
|
||||
void onTick();
|
||||
|
||||
struct SANRData {
|
||||
SANRData(PHLWINDOW pWindow);
|
||||
~SANRData();
|
||||
|
||||
WP<CXWaylandSurface> xwaylandSurface;
|
||||
WP<CXDGWMBase> xdgBase;
|
||||
|
||||
int missedResponses = 0;
|
||||
std::thread dialogThread;
|
||||
SP<Hyprutils::OS::CProcess> dialogProc;
|
||||
std::atomic<bool> dialogThreadExited = false;
|
||||
std::atomic<bool> dialogThreadSaidWait = false;
|
||||
|
||||
void runDialog(const std::string& title, const std::string& appName, const std::string appClass, pid_t dialogWmPID);
|
||||
bool isThreadRunning();
|
||||
void killDialog() const;
|
||||
bool isDefunct() const;
|
||||
bool fitsWindow(PHLWINDOW pWindow) const;
|
||||
pid_t getPid() const;
|
||||
void ping();
|
||||
};
|
||||
|
||||
void onResponse(SP<SANRData> data);
|
||||
bool isNotResponding(SP<SANRData> data);
|
||||
SP<SANRData> dataFor(PHLWINDOW pWindow);
|
||||
SP<SANRData> dataFor(SP<CXDGWMBase> wmBase);
|
||||
SP<SANRData> dataFor(SP<CXWaylandSurface> pXwaylandSurface);
|
||||
|
||||
std::vector<SP<SANRData>> m_data;
|
||||
};
|
||||
|
||||
inline UP<CANRManager> g_pANRManager;
|
@@ -357,21 +357,6 @@ void CHyprAnimationManager::animationSlide(PHLWINDOW pWindow, std::string force,
|
||||
*pWindow->m_vRealPosition = posOffset;
|
||||
}
|
||||
|
||||
void CHyprAnimationManager::animationGnomed(PHLWINDOW pWindow, bool close) {
|
||||
const auto GOALPOS = pWindow->m_vRealPosition->goal();
|
||||
const auto GOALSIZE = pWindow->m_vRealSize->goal();
|
||||
|
||||
if (close) {
|
||||
*pWindow->m_vRealPosition = GOALPOS + Vector2D{0.F, GOALSIZE.y / 2.F};
|
||||
*pWindow->m_vRealSize = Vector2D{GOALSIZE.x, 0.F};
|
||||
} else {
|
||||
pWindow->m_vRealPosition->setValueAndWarp(GOALPOS + Vector2D{0.F, GOALSIZE.y / 2.F});
|
||||
pWindow->m_vRealSize->setValueAndWarp(Vector2D{GOALSIZE.x, 0.F});
|
||||
*pWindow->m_vRealPosition = GOALPOS;
|
||||
*pWindow->m_vRealSize = GOALSIZE;
|
||||
}
|
||||
}
|
||||
|
||||
void CHyprAnimationManager::onWindowPostCreateClose(PHLWINDOW pWindow, bool close) {
|
||||
if (!close) {
|
||||
pWindow->m_vRealPosition->setConfig(g_pConfigManager->getAnimationPropertyConfig("windowsIn"));
|
||||
@@ -402,9 +387,7 @@ void CHyprAnimationManager::onWindowPostCreateClose(PHLWINDOW pWindow, bool clos
|
||||
if (STYLE.starts_with("slide")) {
|
||||
CVarList animList2(STYLE, 0, 's');
|
||||
animationSlide(pWindow, animList2[1], close);
|
||||
} else if (STYLE == "gnomed" || STYLE == "gnome")
|
||||
animationGnomed(pWindow, close);
|
||||
else {
|
||||
} else {
|
||||
// anim popin, fallback
|
||||
|
||||
float minPerc = 0.f;
|
||||
@@ -422,8 +405,6 @@ void CHyprAnimationManager::onWindowPostCreateClose(PHLWINDOW pWindow, bool clos
|
||||
} else {
|
||||
if (animList[0] == "slide")
|
||||
animationSlide(pWindow, animList[1], close);
|
||||
else if (animList[0] == "gnomed" || animList[0] == "gnome")
|
||||
animationGnomed(pWindow, close);
|
||||
else {
|
||||
// anim popin, fallback
|
||||
|
||||
@@ -444,7 +425,7 @@ void CHyprAnimationManager::onWindowPostCreateClose(PHLWINDOW pWindow, bool clos
|
||||
|
||||
std::string CHyprAnimationManager::styleValidInConfigVar(const std::string& config, const std::string& style) {
|
||||
if (config.starts_with("window")) {
|
||||
if (style.starts_with("slide") || style == "gnome" || style == "gnomed")
|
||||
if (style.starts_with("slide"))
|
||||
return "";
|
||||
else if (style.starts_with("popin")) {
|
||||
// try parsing
|
||||
|
@@ -59,7 +59,6 @@ class CHyprAnimationManager : public Hyprutils::Animation::CAnimationManager {
|
||||
// Anim stuff
|
||||
void animationPopin(PHLWINDOW, bool close = false, float minPerc = 0.f);
|
||||
void animationSlide(PHLWINDOW, std::string force = "", bool close = false);
|
||||
void animationGnomed(PHLWINDOW, bool close = false);
|
||||
};
|
||||
|
||||
inline UP<CHyprAnimationManager> g_pAnimationManager;
|
||||
|
@@ -9,10 +9,9 @@
|
||||
#include <sys/un.h>
|
||||
#include <unistd.h>
|
||||
#include <cstring>
|
||||
using namespace Hyprutils::OS;
|
||||
|
||||
CEventManager::CEventManager() : m_iSocketFD(socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0)) {
|
||||
if (!m_iSocketFD.isValid()) {
|
||||
if (m_iSocketFD < 0) {
|
||||
Debug::log(ERR, "Couldn't start the Hyprland Socket 2. (1) IPC will not work.");
|
||||
return;
|
||||
}
|
||||
@@ -26,27 +25,31 @@ CEventManager::CEventManager() : m_iSocketFD(socket(AF_UNIX, SOCK_STREAM | SOCK_
|
||||
|
||||
strncpy(SERVERADDRESS.sun_path, PATH.c_str(), sizeof(SERVERADDRESS.sun_path) - 1);
|
||||
|
||||
if (bind(m_iSocketFD.get(), (sockaddr*)&SERVERADDRESS, SUN_LEN(&SERVERADDRESS)) < 0) {
|
||||
if (bind(m_iSocketFD, (sockaddr*)&SERVERADDRESS, SUN_LEN(&SERVERADDRESS)) < 0) {
|
||||
Debug::log(ERR, "Couldn't bind the Hyprland Socket 2. (3) IPC will not work.");
|
||||
return;
|
||||
}
|
||||
|
||||
// 10 max queued.
|
||||
if (listen(m_iSocketFD.get(), 10) < 0) {
|
||||
if (listen(m_iSocketFD, 10) < 0) {
|
||||
Debug::log(ERR, "Couldn't listen on the Hyprland Socket 2. (4) IPC will not work.");
|
||||
return;
|
||||
}
|
||||
|
||||
m_pEventSource = wl_event_loop_add_fd(g_pCompositor->m_sWLEventLoop, m_iSocketFD.get(), WL_EVENT_READABLE, onClientEvent, nullptr);
|
||||
m_pEventSource = wl_event_loop_add_fd(g_pCompositor->m_sWLEventLoop, m_iSocketFD, WL_EVENT_READABLE, onClientEvent, nullptr);
|
||||
}
|
||||
|
||||
CEventManager::~CEventManager() {
|
||||
for (const auto& client : m_vClients) {
|
||||
wl_event_source_remove(client.eventSource);
|
||||
close(client.fd);
|
||||
}
|
||||
|
||||
if (m_pEventSource != nullptr)
|
||||
wl_event_source_remove(m_pEventSource);
|
||||
|
||||
if (m_iSocketFD >= 0)
|
||||
close(m_iSocketFD);
|
||||
}
|
||||
|
||||
int CEventManager::onServerEvent(int fd, uint32_t mask, void* data) {
|
||||
@@ -63,31 +66,33 @@ int CEventManager::onServerEvent(int fd, uint32_t mask) {
|
||||
|
||||
wl_event_source_remove(m_pEventSource);
|
||||
m_pEventSource = nullptr;
|
||||
m_iSocketFD.reset();
|
||||
close(fd);
|
||||
m_iSocketFD = -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
sockaddr_in clientAddress;
|
||||
socklen_t clientSize = sizeof(clientAddress);
|
||||
CFileDescriptor ACCEPTEDCONNECTION{accept4(m_iSocketFD.get(), (sockaddr*)&clientAddress, &clientSize, SOCK_CLOEXEC | SOCK_NONBLOCK)};
|
||||
if (!ACCEPTEDCONNECTION.isValid()) {
|
||||
sockaddr_in clientAddress;
|
||||
socklen_t clientSize = sizeof(clientAddress);
|
||||
const auto ACCEPTEDCONNECTION = accept4(m_iSocketFD, (sockaddr*)&clientAddress, &clientSize, SOCK_CLOEXEC | SOCK_NONBLOCK);
|
||||
if (ACCEPTEDCONNECTION < 0) {
|
||||
if (errno != EAGAIN) {
|
||||
Debug::log(ERR, "Socket2 failed receiving connection, errno: {}", errno);
|
||||
wl_event_source_remove(m_pEventSource);
|
||||
m_pEventSource = nullptr;
|
||||
m_iSocketFD.reset();
|
||||
close(fd);
|
||||
m_iSocketFD = -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Debug::log(LOG, "Socket2 accepted a new client at FD {}", ACCEPTEDCONNECTION.get());
|
||||
Debug::log(LOG, "Socket2 accepted a new client at FD {}", ACCEPTEDCONNECTION);
|
||||
|
||||
// add to event loop so we can close it when we need to
|
||||
auto* eventSource = wl_event_loop_add_fd(g_pCompositor->m_sWLEventLoop, ACCEPTEDCONNECTION.get(), 0, onServerEvent, nullptr);
|
||||
auto* eventSource = wl_event_loop_add_fd(g_pCompositor->m_sWLEventLoop, ACCEPTEDCONNECTION, 0, onServerEvent, nullptr);
|
||||
m_vClients.emplace_back(SClient{
|
||||
std::move(ACCEPTEDCONNECTION),
|
||||
ACCEPTEDCONNECTION,
|
||||
{},
|
||||
eventSource,
|
||||
});
|
||||
@@ -108,7 +113,7 @@ int CEventManager::onClientEvent(int fd, uint32_t mask) {
|
||||
// send all queued events
|
||||
while (!CLIENTIT->events.empty()) {
|
||||
const auto& event = CLIENTIT->events.front();
|
||||
if (write(CLIENTIT->fd.get(), event->c_str(), event->length()) < 0)
|
||||
if (write(CLIENTIT->fd, event->c_str(), event->length()) < 0)
|
||||
break;
|
||||
|
||||
CLIENTIT->events.erase(CLIENTIT->events.begin());
|
||||
@@ -123,12 +128,13 @@ int CEventManager::onClientEvent(int fd, uint32_t mask) {
|
||||
}
|
||||
|
||||
std::vector<CEventManager::SClient>::iterator CEventManager::findClientByFD(int fd) {
|
||||
return std::find_if(m_vClients.begin(), m_vClients.end(), [fd](const auto& client) { return client.fd.get() == fd; });
|
||||
return std::find_if(m_vClients.begin(), m_vClients.end(), [fd](const auto& client) { return client.fd == fd; });
|
||||
}
|
||||
|
||||
std::vector<CEventManager::SClient>::iterator CEventManager::removeClientByFD(int fd) {
|
||||
const auto CLIENTIT = findClientByFD(fd);
|
||||
wl_event_source_remove(CLIENTIT->eventSource);
|
||||
close(fd);
|
||||
|
||||
return m_vClients.erase(CLIENTIT);
|
||||
}
|
||||
@@ -151,11 +157,11 @@ void CEventManager::postEvent(const SHyprIPCEvent& event) {
|
||||
for (auto it = m_vClients.begin(); it != m_vClients.end();) {
|
||||
// try to send the event immediately if the queue is empty
|
||||
const auto QUEUESIZE = it->events.size();
|
||||
if (QUEUESIZE > 0 || write(it->fd.get(), sharedEvent->c_str(), sharedEvent->length()) < 0) {
|
||||
if (QUEUESIZE > 0 || write(it->fd, sharedEvent->c_str(), sharedEvent->length()) < 0) {
|
||||
if (QUEUESIZE >= MAX_QUEUED_EVENTS) {
|
||||
// too many events queued, remove the client
|
||||
Debug::log(ERR, "Socket2 fd {} overflowed event queue, removing", it->fd.get());
|
||||
it = removeClientByFD(it->fd.get());
|
||||
Debug::log(ERR, "Socket2 fd {} overflowed event queue, removing", it->fd);
|
||||
it = removeClientByFD(it->fd);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
#include <vector>
|
||||
#include <hyprutils/os/FileDescriptor.hpp>
|
||||
#include <vector>
|
||||
|
||||
#include "../defines.hpp"
|
||||
#include "../helpers/memory/Memory.hpp"
|
||||
|
||||
@@ -26,19 +27,19 @@ class CEventManager {
|
||||
int onClientEvent(int fd, uint32_t mask);
|
||||
|
||||
struct SClient {
|
||||
Hyprutils::OS::CFileDescriptor fd;
|
||||
std::vector<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);
|
||||
std::vector<SClient>::iterator removeClientByFD(int fd);
|
||||
|
||||
private:
|
||||
Hyprutils::OS::CFileDescriptor m_iSocketFD;
|
||||
wl_event_source* m_pEventSource = nullptr;
|
||||
int m_iSocketFD = -1;
|
||||
wl_event_source* m_pEventSource = nullptr;
|
||||
|
||||
std::vector<SClient> m_vClients;
|
||||
std::vector<SClient> m_vClients;
|
||||
};
|
||||
|
||||
inline UP<CEventManager> g_pEventManager;
|
||||
|
@@ -12,6 +12,8 @@
|
||||
#include "TokenManager.hpp"
|
||||
#include "eventLoop/EventLoopManager.hpp"
|
||||
#include "debug/Log.hpp"
|
||||
#include "helpers/varlist/VarList.hpp"
|
||||
#include "../helpers/signal/Signal.hpp"
|
||||
#include "../managers/HookSystemManager.hpp"
|
||||
#include "../managers/input/InputManager.hpp"
|
||||
#include "../managers/LayoutManager.hpp"
|
||||
@@ -26,9 +28,7 @@
|
||||
#include <cstring>
|
||||
|
||||
#include <hyprutils/string/String.hpp>
|
||||
#include <hyprutils/os/FileDescriptor.hpp>
|
||||
using namespace Hyprutils::String;
|
||||
using namespace Hyprutils::OS;
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <fcntl.h>
|
||||
@@ -113,7 +113,6 @@ CKeybindManager::CKeybindManager() {
|
||||
m_mDispatchers["focuswindowbyclass"] = focusWindow;
|
||||
m_mDispatchers["focuswindow"] = focusWindow;
|
||||
m_mDispatchers["tagwindow"] = tagWindow;
|
||||
m_mDispatchers["toggleswallow"] = toggleSwallow;
|
||||
m_mDispatchers["submap"] = setSubmap;
|
||||
m_mDispatchers["pass"] = pass;
|
||||
m_mDispatchers["sendshortcut"] = sendshortcut;
|
||||
@@ -368,7 +367,7 @@ bool CKeybindManager::tryMoveFocusToMonitor(PHLMONITOR monitor) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void CKeybindManager::switchToWindow(PHLWINDOW PWINDOWTOCHANGETO, bool preserveFocusHistory) {
|
||||
void CKeybindManager::switchToWindow(PHLWINDOW PWINDOWTOCHANGETO) {
|
||||
static auto PFOLLOWMOUSE = CConfigValue<Hyprlang::INT>("input:follow_mouse");
|
||||
static auto PNOWARPS = CConfigValue<Hyprlang::INT>("cursor:no_warps");
|
||||
|
||||
@@ -387,7 +386,7 @@ void CKeybindManager::switchToWindow(PHLWINDOW PWINDOWTOCHANGETO, bool preserveF
|
||||
if (!PWINDOWTOCHANGETO->m_bPinned)
|
||||
g_pCompositor->setWindowFullscreenInternal(PLASTWINDOW, FSMODE_NONE);
|
||||
|
||||
g_pCompositor->focusWindow(PWINDOWTOCHANGETO, nullptr, preserveFocusHistory);
|
||||
g_pCompositor->focusWindow(PWINDOWTOCHANGETO);
|
||||
|
||||
if (!PWINDOWTOCHANGETO->m_bPinned)
|
||||
g_pCompositor->setWindowFullscreenInternal(PWINDOWTOCHANGETO, MODE);
|
||||
@@ -397,7 +396,7 @@ void CKeybindManager::switchToWindow(PHLWINDOW PWINDOWTOCHANGETO, bool preserveF
|
||||
PWINDOWTOCHANGETO->m_vRealSize->warp();
|
||||
} else {
|
||||
updateRelativeCursorCoords();
|
||||
g_pCompositor->focusWindow(PWINDOWTOCHANGETO, nullptr, preserveFocusHistory);
|
||||
g_pCompositor->focusWindow(PWINDOWTOCHANGETO);
|
||||
PWINDOWTOCHANGETO->warpCursor();
|
||||
|
||||
// Move mouse focus to the new window if required by current follow_mouse and warp modes
|
||||
@@ -854,18 +853,19 @@ bool CKeybindManager::handleVT(xkb_keysym_t keysym) {
|
||||
const unsigned int TTY = keysym - XKB_KEY_XF86Switch_VT_1 + 1;
|
||||
|
||||
// vtnr is bugged for some reason.
|
||||
unsigned int ttynum = 0;
|
||||
Hyprutils::OS::CFileDescriptor fd{open("/dev/tty", O_RDONLY | O_NOCTTY)};
|
||||
if (fd.isValid()) {
|
||||
unsigned int ttynum = 0;
|
||||
int fd;
|
||||
if ((fd = open("/dev/tty", O_RDONLY | O_NOCTTY)) >= 0) {
|
||||
#if defined(VT_GETSTATE)
|
||||
struct vt_stat st;
|
||||
if (!ioctl(fd.get(), VT_GETSTATE, &st))
|
||||
if (!ioctl(fd, VT_GETSTATE, &st))
|
||||
ttynum = st.v_active;
|
||||
#elif defined(VT_GETACTIVE)
|
||||
int vt;
|
||||
if (!ioctl(fd.get(), VT_GETACTIVE, &vt))
|
||||
if (!ioctl(fd, VT_GETACTIVE, &vt))
|
||||
ttynum = vt;
|
||||
#endif
|
||||
close(fd);
|
||||
}
|
||||
|
||||
if (ttynum == TTY)
|
||||
@@ -944,11 +944,11 @@ uint64_t CKeybindManager::spawnRawProc(std::string args, PHLWORKSPACE pInitialWo
|
||||
Debug::log(LOG, "Unable to create pipe for fork");
|
||||
}
|
||||
|
||||
CFileDescriptor pipeSock[2] = {CFileDescriptor{socket[0]}, CFileDescriptor{socket[1]}};
|
||||
|
||||
pid_t child, grandchild;
|
||||
pid_t child, grandchild;
|
||||
child = fork();
|
||||
if (child < 0) {
|
||||
close(socket[0]);
|
||||
close(socket[1]);
|
||||
Debug::log(LOG, "Fail to create the first fork");
|
||||
return 0;
|
||||
}
|
||||
@@ -967,24 +967,22 @@ uint64_t CKeybindManager::spawnRawProc(std::string args, PHLWORKSPACE pInitialWo
|
||||
setenv(e.first.c_str(), e.second.c_str(), 1);
|
||||
}
|
||||
setenv("WAYLAND_DISPLAY", g_pCompositor->m_szWLDisplaySocket.c_str(), 1);
|
||||
|
||||
int devnull = open("/dev/null", O_WRONLY | O_CLOEXEC);
|
||||
if (devnull != -1) {
|
||||
dup2(devnull, STDOUT_FILENO);
|
||||
dup2(devnull, STDERR_FILENO);
|
||||
close(devnull);
|
||||
}
|
||||
|
||||
close(socket[0]);
|
||||
close(socket[1]);
|
||||
execl("/bin/sh", "/bin/sh", "-c", args.c_str(), nullptr);
|
||||
// exit grandchild
|
||||
_exit(0);
|
||||
}
|
||||
write(pipeSock[1].get(), &grandchild, sizeof(grandchild));
|
||||
close(socket[0]);
|
||||
write(socket[1], &grandchild, sizeof(grandchild));
|
||||
close(socket[1]);
|
||||
// exit child
|
||||
_exit(0);
|
||||
}
|
||||
// run in parent
|
||||
read(pipeSock[0].get(), &grandchild, sizeof(grandchild));
|
||||
close(socket[1]);
|
||||
read(socket[0], &grandchild, sizeof(grandchild));
|
||||
close(socket[0]);
|
||||
// clear child and leave grandchild to init
|
||||
waitpid(child, nullptr, 0);
|
||||
if (grandchild < 0) {
|
||||
@@ -1043,7 +1041,7 @@ SDispatchResult CKeybindManager::killWindow(std::string args) {
|
||||
}
|
||||
|
||||
SDispatchResult CKeybindManager::signalActive(std::string args) {
|
||||
if (!isNumber(args))
|
||||
if (!std::all_of(args.begin(), args.end(), ::isdigit))
|
||||
return {.success = false, .error = "signalActive: signal has to be int"};
|
||||
|
||||
try {
|
||||
@@ -1482,7 +1480,7 @@ SDispatchResult CKeybindManager::moveFocusTo(std::string args) {
|
||||
}
|
||||
|
||||
const auto PWINDOWTOCHANGETO = *PFULLCYCLE && PLASTWINDOW->isFullscreen() ?
|
||||
g_pCompositor->getWindowCycle(PLASTWINDOW, true, {}, false, arg != 'd' && arg != 'b' && arg != 'r') :
|
||||
(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.
|
||||
@@ -1723,7 +1721,7 @@ SDispatchResult CKeybindManager::changeGroupActive(std::string args) {
|
||||
// index starts from '1'; '0' means last window
|
||||
const int INDEX = std::stoi(args);
|
||||
if (INDEX > PWINDOW->getGroupSize())
|
||||
return {.success = false, .error = "Index too big, there aren't that many windows in this group"};
|
||||
return {};
|
||||
if (INDEX == 0)
|
||||
PWINDOW->setGroupCurrent(PWINDOW->getGroupTail());
|
||||
else
|
||||
@@ -1916,6 +1914,7 @@ SDispatchResult CKeybindManager::workspaceOpt(std::string args) {
|
||||
if (PWORKSPACE->m_bDefaultFloating) {
|
||||
w->m_vRealPosition->setValueAndWarp(SAVEDPOS);
|
||||
w->m_vRealSize->setValueAndWarp(SAVEDSIZE);
|
||||
w->sendWindowSize(SAVEDSIZE);
|
||||
*w->m_vRealSize = w->m_vRealSize->value() + Vector2D(4, 4);
|
||||
*w->m_vRealPosition = w->m_vRealPosition->value() - Vector2D(2, 2);
|
||||
}
|
||||
@@ -1986,7 +1985,7 @@ SDispatchResult CKeybindManager::moveCurrentWorkspaceToMonitor(std::string args)
|
||||
|
||||
SDispatchResult CKeybindManager::moveWorkspaceToMonitor(std::string args) {
|
||||
if (!args.contains(' '))
|
||||
return {.success = false, .error = "Invalid arguments, expected: workspace monitor"};
|
||||
return {};
|
||||
|
||||
std::string workspace = args.substr(0, args.find_first_of(' '));
|
||||
std::string monitor = args.substr(args.find_first_of(' ') + 1);
|
||||
@@ -2129,16 +2128,13 @@ SDispatchResult CKeybindManager::forceRendererReload(std::string args) {
|
||||
SDispatchResult CKeybindManager::resizeActive(std::string args) {
|
||||
const auto PLASTWINDOW = g_pCompositor->m_pLastWindow.lock();
|
||||
|
||||
if (!PLASTWINDOW)
|
||||
return {.success = false, .error = "No window found"};
|
||||
|
||||
if (PLASTWINDOW->isFullscreen())
|
||||
return {.success = false, .error = "Window is fullscreen"};
|
||||
if (!PLASTWINDOW || PLASTWINDOW->isFullscreen())
|
||||
return {};
|
||||
|
||||
const auto SIZ = g_pCompositor->parseWindowVectorArgsRelative(args, PLASTWINDOW->m_vRealSize->goal());
|
||||
|
||||
if (SIZ.x < 1 || SIZ.y < 1)
|
||||
return {.success = false, .error = "Invalid size provided"};
|
||||
return {};
|
||||
|
||||
g_pLayoutManager->getCurrentLayout()->resizeActiveWindow(SIZ - PLASTWINDOW->m_vRealSize->goal());
|
||||
|
||||
@@ -2151,11 +2147,8 @@ SDispatchResult CKeybindManager::resizeActive(std::string args) {
|
||||
SDispatchResult CKeybindManager::moveActive(std::string args) {
|
||||
const auto PLASTWINDOW = g_pCompositor->m_pLastWindow.lock();
|
||||
|
||||
if (!PLASTWINDOW)
|
||||
return {.success = false, .error = "No window found"};
|
||||
|
||||
if (PLASTWINDOW->isFullscreen())
|
||||
return {.success = false, .error = "Window is fullscreen"};
|
||||
if (!PLASTWINDOW || PLASTWINDOW->isFullscreen())
|
||||
return {};
|
||||
|
||||
const auto POS = g_pCompositor->parseWindowVectorArgsRelative(args, PLASTWINDOW->m_vRealPosition->goal());
|
||||
|
||||
@@ -2177,7 +2170,7 @@ SDispatchResult CKeybindManager::moveWindow(std::string args) {
|
||||
}
|
||||
|
||||
if (PWINDOW->isFullscreen())
|
||||
return {.success = false, .error = "Window is fullscreen"};
|
||||
return {};
|
||||
|
||||
const auto POS = g_pCompositor->parseWindowVectorArgsRelative(MOVECMD, PWINDOW->m_vRealPosition->goal());
|
||||
|
||||
@@ -2199,12 +2192,12 @@ SDispatchResult CKeybindManager::resizeWindow(std::string args) {
|
||||
}
|
||||
|
||||
if (PWINDOW->isFullscreen())
|
||||
return {.success = false, .error = "Window is fullscreen"};
|
||||
return {};
|
||||
|
||||
const auto SIZ = g_pCompositor->parseWindowVectorArgsRelative(MOVECMD, PWINDOW->m_vRealSize->goal());
|
||||
|
||||
if (SIZ.x < 1 || SIZ.y < 1)
|
||||
return {.success = false, .error = "Invalid size provided"};
|
||||
return {};
|
||||
|
||||
g_pLayoutManager->getCurrentLayout()->resizeActiveWindow(SIZ - PWINDOW->m_vRealSize->goal(), CORNER_NONE, PWINDOW);
|
||||
|
||||
@@ -2235,13 +2228,11 @@ SDispatchResult CKeybindManager::circleNext(std::string arg) {
|
||||
floatStatus = true;
|
||||
|
||||
const auto VISIBLE = args.contains("visible") || args.contains("v");
|
||||
const auto PREV = args.contains("prev") || args.contains("p") || args.contains("last") || args.contains("l");
|
||||
const auto NEXT = args.contains("next") || args.contains("n"); // prev is default in classic alt+tab
|
||||
const auto HIST = args.contains("hist") || args.contains("h");
|
||||
const auto& w = HIST ? g_pCompositor->getWindowCycleHist(g_pCompositor->m_pLastWindow, true, floatStatus, VISIBLE, NEXT) :
|
||||
g_pCompositor->getWindowCycle(g_pCompositor->m_pLastWindow.lock(), true, floatStatus, VISIBLE, PREV);
|
||||
const auto& w = (args.contains("prev") || args.contains("p") || args.contains("last") || args.contains("l")) ?
|
||||
g_pCompositor->getPrevWindowOnWorkspace(g_pCompositor->m_pLastWindow.lock(), true, floatStatus, VISIBLE) :
|
||||
g_pCompositor->getNextWindowOnWorkspace(g_pCompositor->m_pLastWindow.lock(), true, floatStatus, VISIBLE);
|
||||
|
||||
switchToWindow(w, HIST);
|
||||
switchToWindow(w);
|
||||
|
||||
return {};
|
||||
}
|
||||
@@ -2250,7 +2241,7 @@ SDispatchResult CKeybindManager::focusWindow(std::string regexp) {
|
||||
const auto PWINDOW = g_pCompositor->getWindowByRegex(regexp);
|
||||
|
||||
if (!PWINDOW)
|
||||
return {.success = false, .error = "No such window found"};
|
||||
return {};
|
||||
|
||||
Debug::log(LOG, "Focusing to window name: {}", PWINDOW->m_szTitle);
|
||||
|
||||
@@ -2310,7 +2301,7 @@ SDispatchResult CKeybindManager::tagWindow(std::string args) {
|
||||
else if (vars.size() == 2)
|
||||
PWINDOW = g_pCompositor->getWindowByRegex(vars[1]);
|
||||
else
|
||||
return {.success = false, .error = "Invalid number of arguments, expected 1 or 2 arguments"};
|
||||
return {};
|
||||
|
||||
if (PWINDOW && PWINDOW->m_tags.applyTag(vars[0])) {
|
||||
PWINDOW->updateDynamicRules();
|
||||
@@ -2320,27 +2311,6 @@ SDispatchResult CKeybindManager::tagWindow(std::string args) {
|
||||
return {};
|
||||
}
|
||||
|
||||
SDispatchResult CKeybindManager::toggleSwallow(std::string args) {
|
||||
PHLWINDOWREF pWindow = g_pCompositor->m_pLastWindow;
|
||||
|
||||
if (!valid(pWindow) || !valid(pWindow->m_pSwallowed))
|
||||
return {};
|
||||
|
||||
if (pWindow->m_pSwallowed->m_bCurrentlySwallowed) {
|
||||
// Unswallow
|
||||
pWindow->m_pSwallowed->m_bCurrentlySwallowed = false;
|
||||
pWindow->m_pSwallowed->setHidden(false);
|
||||
g_pLayoutManager->getCurrentLayout()->onWindowCreated(pWindow->m_pSwallowed.lock());
|
||||
} else {
|
||||
// Reswallow
|
||||
pWindow->m_pSwallowed->m_bCurrentlySwallowed = true;
|
||||
pWindow->m_pSwallowed->setHidden(true);
|
||||
g_pLayoutManager->getCurrentLayout()->onWindowRemoved(pWindow->m_pSwallowed.lock());
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
SDispatchResult CKeybindManager::setSubmap(std::string submap) {
|
||||
if (submap == "reset" || submap == "") {
|
||||
m_szCurrentSelectedSubmap = "";
|
||||
@@ -2657,12 +2627,18 @@ SDispatchResult CKeybindManager::swapnext(std::string arg) {
|
||||
g_pCompositor->m_pLastWindow->m_pLastCycledWindow.lock() :
|
||||
nullptr;
|
||||
|
||||
const bool NEED_PREV = arg == "last" || arg == "l" || arg == "prev" || arg == "p";
|
||||
toSwap = g_pCompositor->getWindowCycle(PLASTCYCLED ? PLASTCYCLED : PLASTWINDOW, true, std::nullopt, false, NEED_PREV);
|
||||
if (arg == "last" || arg == "l" || arg == "prev" || arg == "p")
|
||||
toSwap = g_pCompositor->getPrevWindowOnWorkspace(PLASTCYCLED ? PLASTCYCLED : PLASTWINDOW, true);
|
||||
else
|
||||
toSwap = g_pCompositor->getNextWindowOnWorkspace(PLASTCYCLED ? PLASTCYCLED : PLASTWINDOW, true);
|
||||
|
||||
// sometimes we may come back to ourselves.
|
||||
if (toSwap == PLASTWINDOW)
|
||||
toSwap = g_pCompositor->getWindowCycle(PLASTWINDOW, true, std::nullopt, false, NEED_PREV);
|
||||
if (toSwap == PLASTWINDOW) {
|
||||
if (arg == "last" || arg == "l" || arg == "prev" || arg == "p")
|
||||
toSwap = g_pCompositor->getPrevWindowOnWorkspace(PLASTWINDOW, true);
|
||||
else
|
||||
toSwap = g_pCompositor->getNextWindowOnWorkspace(PLASTWINDOW, true);
|
||||
}
|
||||
|
||||
g_pLayoutManager->getCurrentLayout()->switchWindows(PLASTWINDOW, toSwap);
|
||||
|
||||
@@ -2680,10 +2656,7 @@ SDispatchResult CKeybindManager::swapActiveWorkspaces(std::string args) {
|
||||
const auto PMON1 = g_pCompositor->getMonitorFromString(MON1);
|
||||
const auto PMON2 = g_pCompositor->getMonitorFromString(MON2);
|
||||
|
||||
if (!PMON1 || !PMON2)
|
||||
return {.success = false, .error = "No such monitor found"};
|
||||
|
||||
if (PMON1 == PMON2)
|
||||
if (!PMON1 || !PMON2 || PMON1 == PMON2)
|
||||
return {};
|
||||
|
||||
g_pCompositor->swapActiveWorkspaces(PMON1, PMON2);
|
||||
@@ -2706,7 +2679,7 @@ SDispatchResult CKeybindManager::pinActive(std::string args) {
|
||||
}
|
||||
|
||||
if (!PWINDOW->m_bIsFloating || PWINDOW->isFullscreen())
|
||||
return {.success = false, .error = "Window does not qualify to be pinned"};
|
||||
return {};
|
||||
|
||||
PWINDOW->m_bPinned = !PWINDOW->m_bPinned;
|
||||
|
||||
@@ -2827,7 +2800,6 @@ SDispatchResult CKeybindManager::lockGroups(std::string args) {
|
||||
g_pKeybindManager->m_bGroupsLocked = false;
|
||||
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"lockgroups", g_pKeybindManager->m_bGroupsLocked ? "1" : "0"});
|
||||
g_pCompositor->updateAllWindowsAnimatedDecorationValues();
|
||||
|
||||
return {};
|
||||
}
|
||||
@@ -2835,11 +2807,8 @@ SDispatchResult CKeybindManager::lockGroups(std::string args) {
|
||||
SDispatchResult CKeybindManager::lockActiveGroup(std::string args) {
|
||||
const auto PWINDOW = g_pCompositor->m_pLastWindow.lock();
|
||||
|
||||
if (!PWINDOW)
|
||||
return {.success = false, .error = "No window found"};
|
||||
|
||||
if (!PWINDOW->m_sGroupData.pNextWindow.lock())
|
||||
return {.success = false, .error = "Not a group"};
|
||||
if (!PWINDOW || !PWINDOW->m_sGroupData.pNextWindow.lock())
|
||||
return {};
|
||||
|
||||
const auto PHEAD = PWINDOW->getGroupHead();
|
||||
|
||||
@@ -2960,7 +2929,7 @@ SDispatchResult CKeybindManager::moveOutOfGroup(std::string args) {
|
||||
static auto PIGNOREGROUPLOCK = CConfigValue<Hyprlang::INT>("binds:ignore_group_lock");
|
||||
|
||||
if (!*PIGNOREGROUPLOCK && g_pKeybindManager->m_bGroupsLocked)
|
||||
return {.success = false, .error = "Groups locked"};
|
||||
return {};
|
||||
|
||||
PHLWINDOW PWINDOW = nullptr;
|
||||
|
||||
@@ -2969,11 +2938,8 @@ SDispatchResult CKeybindManager::moveOutOfGroup(std::string args) {
|
||||
else
|
||||
PWINDOW = g_pCompositor->m_pLastWindow.lock();
|
||||
|
||||
if (!PWINDOW)
|
||||
return {.success = false, .error = "No window found"};
|
||||
|
||||
if (!PWINDOW->m_sGroupData.pNextWindow.lock())
|
||||
return {.success = false, .error = "Window not in a group"};
|
||||
if (!PWINDOW || !PWINDOW->m_sGroupData.pNextWindow.lock())
|
||||
return {};
|
||||
|
||||
moveWindowOutOfGroup(PWINDOW);
|
||||
|
||||
@@ -2991,10 +2957,7 @@ SDispatchResult CKeybindManager::moveWindowOrGroup(std::string args) {
|
||||
}
|
||||
|
||||
const auto PWINDOW = g_pCompositor->m_pLastWindow.lock();
|
||||
if (!PWINDOW)
|
||||
return {.success = false, .error = "No window found"};
|
||||
|
||||
if (PWINDOW->isFullscreen())
|
||||
if (!PWINDOW || PWINDOW->isFullscreen())
|
||||
return {};
|
||||
|
||||
if (!*PIGNOREGROUPLOCK && g_pKeybindManager->m_bGroupsLocked) {
|
||||
@@ -3004,7 +2967,7 @@ SDispatchResult CKeybindManager::moveWindowOrGroup(std::string args) {
|
||||
|
||||
const auto PWINDOWINDIR = g_pCompositor->getWindowInDirection(PWINDOW, arg);
|
||||
|
||||
const bool ISWINDOWGROUP = PWINDOW->m_sGroupData.pNextWindow;
|
||||
const bool ISWINDOWGROUP = PWINDOW->m_sGroupData.pNextWindow.lock().get();
|
||||
const bool ISWINDOWGROUPLOCKED = ISWINDOWGROUP && PWINDOW->getGroupHead()->m_sGroupData.locked;
|
||||
const bool ISWINDOWGROUPSINGLE = ISWINDOWGROUP && PWINDOW->m_sGroupData.pNextWindow.lock() == PWINDOW;
|
||||
|
||||
@@ -3083,11 +3046,8 @@ SDispatchResult CKeybindManager::moveGroupWindow(std::string args) {
|
||||
|
||||
const auto PLASTWINDOW = g_pCompositor->m_pLastWindow.lock();
|
||||
|
||||
if (!PLASTWINDOW)
|
||||
return {.success = false, .error = "No window found"};
|
||||
|
||||
if (!PLASTWINDOW->m_sGroupData.pNextWindow.lock())
|
||||
return {.success = false, .error = "Window not in a group"};
|
||||
if (!PLASTWINDOW || !PLASTWINDOW->m_sGroupData.pNextWindow.lock())
|
||||
return {};
|
||||
|
||||
if ((!BACK && PLASTWINDOW->m_sGroupData.pNextWindow->m_sGroupData.head) || (BACK && PLASTWINDOW->m_sGroupData.head)) {
|
||||
std::swap(PLASTWINDOW->m_sGroupData.head, PLASTWINDOW->m_sGroupData.pNextWindow->m_sGroupData.head);
|
||||
@@ -3178,7 +3138,7 @@ SDispatchResult CKeybindManager::setProp(std::string args) {
|
||||
PWINDOW->m_sWindowData.activeBorderColor = CWindowOverridableVar(colorData, PRIORITY_SET_PROP);
|
||||
else
|
||||
PWINDOW->m_sWindowData.inactiveBorderColor = CWindowOverridableVar(colorData, PRIORITY_SET_PROP);
|
||||
} else if (auto search = NWindowProperties::boolWindowProperties.find(PROP); search != NWindowProperties::boolWindowProperties.end()) {
|
||||
} else if (auto search = g_pConfigManager->mbWindowProperties.find(PROP); search != g_pConfigManager->mbWindowProperties.end()) {
|
||||
auto pWindowDataElement = search->second(PWINDOW);
|
||||
if (VAL == "toggle")
|
||||
*pWindowDataElement = CWindowOverridableVar(!pWindowDataElement->valueOrDefault(), PRIORITY_SET_PROP);
|
||||
@@ -3186,12 +3146,12 @@ SDispatchResult CKeybindManager::setProp(std::string args) {
|
||||
pWindowDataElement->unset(PRIORITY_SET_PROP);
|
||||
else
|
||||
*pWindowDataElement = CWindowOverridableVar((bool)configStringToInt(VAL).value_or(0), PRIORITY_SET_PROP);
|
||||
} else if (auto search = NWindowProperties::intWindowProperties.find(PROP); search != NWindowProperties::intWindowProperties.end()) {
|
||||
} 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 if (const auto V = configStringToInt(VAL); V)
|
||||
*(search->second(PWINDOW)) = CWindowOverridableVar((int)*V, PRIORITY_SET_PROP);
|
||||
} else if (auto search = NWindowProperties::floatWindowProperties.find(PROP); search != NWindowProperties::floatWindowProperties.end()) {
|
||||
} 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 {
|
||||
|
@@ -148,7 +148,7 @@ class CKeybindManager {
|
||||
static bool tryMoveFocusToMonitor(PHLMONITOR monitor);
|
||||
static void moveWindowOutOfGroup(PHLWINDOW pWindow, const std::string& dir = "");
|
||||
static void moveWindowIntoGroup(PHLWINDOW pWindow, PHLWINDOW pWindowInDirection);
|
||||
static void switchToWindow(PHLWINDOW PWINDOWTOCHANGETO, bool preserveFocusHistory = false);
|
||||
static void switchToWindow(PHLWINDOW PWINDOWTOCHANGETO);
|
||||
static uint64_t spawnRawProc(std::string, PHLWORKSPACE pInitialWorkspace);
|
||||
static uint64_t spawnWithRules(std::string, PHLWORKSPACE pInitialWorkspace);
|
||||
|
||||
@@ -199,7 +199,6 @@ class CKeybindManager {
|
||||
static SDispatchResult circleNext(std::string);
|
||||
static SDispatchResult focusWindow(std::string);
|
||||
static SDispatchResult tagWindow(std::string);
|
||||
static SDispatchResult toggleSwallow(std::string);
|
||||
static SDispatchResult setSubmap(std::string);
|
||||
static SDispatchResult pass(std::string);
|
||||
static SDispatchResult sendshortcut(std::string);
|
||||
|
@@ -17,9 +17,6 @@
|
||||
#include <cstring>
|
||||
#include <gbm.h>
|
||||
#include <cairo/cairo.h>
|
||||
#include <hyprutils/utils/ScopeGuard.hpp>
|
||||
|
||||
using namespace Hyprutils::Utils;
|
||||
|
||||
CPointerManager::CPointerManager() {
|
||||
hooks.monitorAdded = g_pHookSystem->hookDynamic("monitorAdded", [this](void* self, SCallbackInfo& info, std::any data) {
|
||||
@@ -274,7 +271,7 @@ void CPointerManager::updateCursorBackend() {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (state->softwareLocks > 0 || g_pConfigManager->shouldUseSoftwareCursors(m) || !attemptHardwareCursor(state)) {
|
||||
if (state->softwareLocks > 0 || g_pConfigManager->shouldUseSoftwareCursors() || !attemptHardwareCursor(state)) {
|
||||
Debug::log(TRACE, "Output {} rejected hardware cursors, falling back to sw", m->szName);
|
||||
state->box = getCursorBoxLogicalForMonitor(state->monitor.lock());
|
||||
state->hardwareFailed = true;
|
||||
@@ -313,18 +310,11 @@ void CPointerManager::onCursorMoved() {
|
||||
recalc = true;
|
||||
}
|
||||
|
||||
if (!state->entered)
|
||||
continue;
|
||||
|
||||
CScopeGuard x([m] { m->onCursorMovedOnMonitor(); });
|
||||
|
||||
if (state->hardwareFailed)
|
||||
if (state->hardwareFailed || !state->entered)
|
||||
continue;
|
||||
|
||||
const auto CURSORPOS = getCursorPosForMonitor(m);
|
||||
m->output->moveCursor(CURSORPOS, m->shouldSkipScheduleFrameOnMouseEvent());
|
||||
|
||||
state->monitor->scanoutNeedsCursorUpdate = true;
|
||||
}
|
||||
|
||||
if (recalc)
|
||||
@@ -384,8 +374,6 @@ bool CPointerManager::setHWCursorBuffer(SP<SMonitorPointerState> state, SP<Aquam
|
||||
if (!state->monitor->shouldSkipScheduleFrameOnMouseEvent())
|
||||
g_pCompositor->scheduleFrameForMonitor(state->monitor.lock(), Aquamarine::IOutput::AQ_SCHEDULE_CURSOR_SHAPE);
|
||||
|
||||
state->monitor->scanoutNeedsCursorUpdate = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -423,9 +411,7 @@ SP<Aquamarine::IBuffer> CPointerManager::renderHWCursorBuffer(SP<CPointerManager
|
||||
}
|
||||
}
|
||||
|
||||
auto backend = state->monitor->output->getBackend();
|
||||
auto primary = backend->getPrimary();
|
||||
state->monitor->cursorSwapchain = Aquamarine::CSwapchain::create(allocator, primary ? primary.lock() : backend);
|
||||
state->monitor->cursorSwapchain = Aquamarine::CSwapchain::create(allocator, state->monitor->output->getBackend());
|
||||
}
|
||||
|
||||
auto options = state->monitor->cursorSwapchain->currentOptions();
|
||||
@@ -489,7 +475,7 @@ SP<Aquamarine::IBuffer> CPointerManager::renderHWCursorBuffer(SP<CPointerManager
|
||||
|
||||
if (flipRB) {
|
||||
for (size_t i = 0; i < shmBuffer.size(); i += 4) {
|
||||
std::swap(shmBuffer[i], shmBuffer[i + 2]); // little-endian!!!!!!
|
||||
std::swap(shmBuffer.at(i), shmBuffer.at(i + 2)); // little-endian!!!!!!
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -621,11 +607,15 @@ void CPointerManager::renderSoftwareCursorsFor(PHLMONITOR pMonitor, timespec* no
|
||||
box.y = std::round(box.y);
|
||||
|
||||
CTexPassElement::SRenderData data;
|
||||
data.tex = texture;
|
||||
data.box = box.round();
|
||||
|
||||
data.tex = texture;
|
||||
data.box = box.round();
|
||||
data.syncTimeline = currentCursorImage.waitTimeline;
|
||||
data.syncPoint = currentCursorImage.waitPoint;
|
||||
g_pHyprRenderer->m_sRenderPass.add(makeShared<CTexPassElement>(data));
|
||||
|
||||
currentCursorImage.waitTimeline.reset();
|
||||
currentCursorImage.waitPoint = 0;
|
||||
|
||||
if (currentCursorImage.surface)
|
||||
currentCursorImage.surface->resource()->frame(now);
|
||||
}
|
||||
@@ -739,8 +729,7 @@ void CPointerManager::damageIfSoftware() {
|
||||
if (mw->monitor.expired() || !mw->monitor->output)
|
||||
continue;
|
||||
|
||||
if ((mw->softwareLocks > 0 || mw->hardwareFailed || g_pConfigManager->shouldUseSoftwareCursors(mw->monitor.lock())) &&
|
||||
b.overlaps({mw->monitor->vecPosition, mw->monitor->vecSize})) {
|
||||
if ((mw->softwareLocks > 0 || mw->hardwareFailed || g_pConfigManager->shouldUseSoftwareCursors()) && b.overlaps({mw->monitor->vecPosition, mw->monitor->vecSize})) {
|
||||
g_pHyprRenderer->damageBox(b, mw->monitor->shouldSkipScheduleFrameOnMouseEvent());
|
||||
break;
|
||||
}
|
||||
|
@@ -148,6 +148,8 @@ class CPointerManager {
|
||||
|
||||
CHyprSignalListener destroySurface;
|
||||
CHyprSignalListener commitSurface;
|
||||
SP<CSyncTimeline> waitTimeline = nullptr;
|
||||
uint64_t waitPoint = 0;
|
||||
} currentCursorImage; // TODO: support various sizes per-output so we can have pixel-perfect cursors
|
||||
|
||||
Vector2D pointerPos = {0, 0};
|
||||
|
@@ -57,23 +57,15 @@
|
||||
#include "../protocols/core/Output.hpp"
|
||||
#include "../protocols/core/Shm.hpp"
|
||||
#include "../protocols/ColorManagement.hpp"
|
||||
#include "../protocols/XXColorManagement.hpp"
|
||||
#include "../protocols/FrogColorManagement.hpp"
|
||||
#include "../protocols/ContentType.hpp"
|
||||
|
||||
#include "../helpers/Monitor.hpp"
|
||||
#include "../render/Renderer.hpp"
|
||||
#include "../Compositor.hpp"
|
||||
#include "content-type-v1.hpp"
|
||||
|
||||
#include <aquamarine/buffer/Buffer.hpp>
|
||||
#include <aquamarine/backend/Backend.hpp>
|
||||
|
||||
// ********************************************************************************************
|
||||
// * IMPORTANT: make sure to .reset() any protocol UP's you create! (put reset in destructor) *
|
||||
// * otherwise Hyprland might crash when exiting. *
|
||||
// ********************************************************************************************
|
||||
|
||||
void CProtocolManager::onMonitorModeChange(PHLMONITOR pMonitor) {
|
||||
const bool ISMIRROR = pMonitor->isMirror();
|
||||
|
||||
@@ -89,18 +81,14 @@ void CProtocolManager::onMonitorModeChange(PHLMONITOR pMonitor) {
|
||||
PROTO::outputs.emplace(pMonitor->szName, makeShared<CWLOutputProtocol>(&wl_output_interface, 4, std::format("WLOutput ({})", pMonitor->szName), pMonitor->self.lock()));
|
||||
}
|
||||
|
||||
if (PROTO::colorManagement && g_pCompositor->shouldChangePreferredImageDescription()) {
|
||||
Debug::log(ERR, "FIXME: color management protocol is enabled, need a preferred image description id");
|
||||
PROTO::colorManagement->onImagePreferredChanged(0);
|
||||
}
|
||||
if (PROTO::colorManagement && g_pCompositor->shouldChangePreferredImageDescription())
|
||||
PROTO::colorManagement->onImagePreferredChanged();
|
||||
}
|
||||
|
||||
CProtocolManager::CProtocolManager() {
|
||||
|
||||
static const auto PENABLEEXPLICIT = CConfigValue<Hyprlang::INT>("render:explicit_sync");
|
||||
static const auto PENABLECM = CConfigValue<Hyprlang::INT>("render:cm_enabled");
|
||||
static const auto PENABLEXXCM = CConfigValue<Hyprlang::INT>("experimental:xx_color_management_v4");
|
||||
static const auto PDEBUGCM = CConfigValue<Hyprlang::INT>("debug:full_cm_proto");
|
||||
|
||||
// Outputs are a bit dumb, we have to agree.
|
||||
static auto P = g_pHookSystem->hookDynamic("monitorAdded", [this](void* self, SCallbackInfo& info, std::any param) {
|
||||
@@ -157,7 +145,7 @@ CProtocolManager::CProtocolManager() {
|
||||
PROTO::constraints = makeUnique<CPointerConstraintsProtocol>(&zwp_pointer_constraints_v1_interface, 1, "PointerConstraints");
|
||||
PROTO::outputPower = makeUnique<COutputPowerProtocol>(&zwlr_output_power_manager_v1_interface, 1, "OutputPower");
|
||||
PROTO::activation = makeUnique<CXDGActivationProtocol>(&xdg_activation_v1_interface, 1, "XDGActivation");
|
||||
PROTO::idle = makeUnique<CIdleNotifyProtocol>(&ext_idle_notifier_v1_interface, 2, "IdleNotify");
|
||||
PROTO::idle = makeUnique<CIdleNotifyProtocol>(&ext_idle_notifier_v1_interface, 1, "IdleNotify");
|
||||
PROTO::lockNotify = makeUnique<CLockNotifyProtocol>(&hyprland_lock_notifier_v1_interface, 1, "IdleNotify");
|
||||
PROTO::sessionLock = makeUnique<CSessionLockProtocol>(&ext_session_lock_manager_v1_interface, 1, "SessionLock");
|
||||
PROTO::ime = makeUnique<CInputMethodV2Protocol>(&zwp_input_method_manager_v2_interface, 1, "IMEv2");
|
||||
@@ -176,23 +164,17 @@ CProtocolManager::CProtocolManager() {
|
||||
PROTO::screencopy = makeUnique<CScreencopyProtocol>(&zwlr_screencopy_manager_v1_interface, 3, "Screencopy");
|
||||
PROTO::toplevelExport = makeUnique<CToplevelExportProtocol>(&hyprland_toplevel_export_manager_v1_interface, 2, "ToplevelExport");
|
||||
PROTO::globalShortcuts = makeUnique<CGlobalShortcutsProtocol>(&hyprland_global_shortcuts_manager_v1_interface, 1, "GlobalShortcuts");
|
||||
PROTO::xdgDialog = makeUnique<CXDGDialogProtocol>(&xdg_wm_dialog_v1_interface, 1, "XDGDialog");
|
||||
PROTO::xdgDialog = makeUnique<CXDGDialogProtocol>(&xdg_dialog_v1_interface, 1, "XDGDialog");
|
||||
PROTO::singlePixel = makeUnique<CSinglePixelProtocol>(&wp_single_pixel_buffer_manager_v1_interface, 1, "SinglePixel");
|
||||
PROTO::securityContext = makeUnique<CSecurityContextProtocol>(&wp_security_context_manager_v1_interface, 1, "SecurityContext");
|
||||
PROTO::ctm = makeUnique<CHyprlandCTMControlProtocol>(&hyprland_ctm_control_manager_v1_interface, 2, "CTMControl");
|
||||
PROTO::ctm = makeUnique<CHyprlandCTMControlProtocol>(&hyprland_ctm_control_manager_v1_interface, 1, "CTMControl");
|
||||
PROTO::hyprlandSurface = makeUnique<CHyprlandSurfaceProtocol>(&hyprland_surface_manager_v1_interface, 2, "HyprlandSurface");
|
||||
PROTO::contentType = makeUnique<CContentTypeProtocol>(&wp_content_type_manager_v1_interface, 1, "ContentType");
|
||||
|
||||
if (*PENABLECM)
|
||||
PROTO::colorManagement = makeUnique<CColorManagementProtocol>(&wp_color_manager_v1_interface, 1, "ColorManagement", *PDEBUGCM);
|
||||
|
||||
if (*PENABLEXXCM && *PENABLECM) {
|
||||
PROTO::xxColorManagement = makeUnique<CXXColorManagementProtocol>(&xx_color_manager_v4_interface, 1, "XXColorManagement");
|
||||
if (*PENABLEXXCM) {
|
||||
PROTO::colorManagement = makeUnique<CColorManagementProtocol>(&xx_color_manager_v4_interface, 1, "ColorManagement");
|
||||
PROTO::frogColorManagement = makeUnique<CFrogColorManagementProtocol>(&frog_color_management_factory_v1_interface, 1, "FrogColorManagement");
|
||||
}
|
||||
|
||||
// ! please read the top of this file before adding another protocol
|
||||
|
||||
for (auto const& b : g_pCompositor->m_pAqBackend->getImplementations()) {
|
||||
if (b->type() != Aquamarine::AQ_BACKEND_DRM)
|
||||
continue;
|
||||
@@ -267,10 +249,6 @@ CProtocolManager::~CProtocolManager() {
|
||||
PROTO::securityContext.reset();
|
||||
PROTO::ctm.reset();
|
||||
PROTO::hyprlandSurface.reset();
|
||||
PROTO::contentType.reset();
|
||||
PROTO::colorManagement.reset();
|
||||
PROTO::xxColorManagement.reset();
|
||||
PROTO::frogColorManagement.reset();
|
||||
|
||||
PROTO::lease.reset();
|
||||
PROTO::sync.reset();
|
||||
|
@@ -606,11 +606,11 @@ void CSeatManager::setGrab(SP<CSeatGrab> grab) {
|
||||
|
||||
if (!refocus) {
|
||||
surf = CWLSurface::fromResource(currentFocus);
|
||||
layer = surf ? surf->getLayer() : nullptr;
|
||||
layer = surf->getLayer();
|
||||
}
|
||||
|
||||
if (!refocus && !layer) {
|
||||
auto popup = surf ? surf->getPopup() : nullptr;
|
||||
auto popup = surf->getPopup();
|
||||
if (popup) {
|
||||
auto parent = popup->getT1Owner();
|
||||
layer = parent->getLayer();
|
||||
|
@@ -89,13 +89,6 @@ void CSessionLockManager::onNewSessionLock(SP<CSessionLock> pLock) {
|
||||
|
||||
g_pCompositor->focusSurface(nullptr);
|
||||
g_pSeatManager->setGrab(nullptr);
|
||||
|
||||
// Normally the locked event is sent after each output rendered a lock screen frame.
|
||||
// When there are no outputs, send it right away.
|
||||
if (g_pCompositor->m_bUnsafeState) {
|
||||
m_pSessionLock->lock->sendLocked();
|
||||
m_pSessionLock->m_hasSentLocked = true;
|
||||
}
|
||||
}
|
||||
|
||||
bool CSessionLockManager::isSessionLocked() {
|
||||
@@ -138,7 +131,8 @@ void CSessionLockManager::onLockscreenRenderedOnMonitor(uint64_t id) {
|
||||
if (!m_pSessionLock || m_pSessionLock->m_hasSentLocked)
|
||||
return;
|
||||
m_pSessionLock->m_lockedMonitors.emplace(id);
|
||||
const bool LOCKED = std::ranges::all_of(g_pCompositor->m_vMonitors, [this](auto m) { return m_pSessionLock->m_lockedMonitors.contains(m->ID); });
|
||||
const auto MONITORS = g_pCompositor->m_vMonitors;
|
||||
const bool LOCKED = std::all_of(MONITORS.begin(), MONITORS.end(), [this](auto m) { return m_pSessionLock->m_lockedMonitors.contains(m->ID); });
|
||||
if (LOCKED && m_pSessionLock->lock->good()) {
|
||||
m_pSessionLock->lock->sendLocked();
|
||||
m_pSessionLock->m_hasSentLocked = true;
|
||||
|
@@ -156,7 +156,9 @@ void CXCursorManager::loadTheme(std::string const& name, int size, float scale)
|
||||
cursors.emplace_back(cursor);
|
||||
}
|
||||
|
||||
syncGsettings();
|
||||
static auto SYNCGSETTINGS = CConfigValue<Hyprlang::INT>("cursor:sync_gsettings_theme");
|
||||
if (*SYNCGSETTINGS)
|
||||
syncGsettings();
|
||||
}
|
||||
|
||||
SP<SXCursors> CXCursorManager::getShape(std::string const& shape, int size, float scale) {
|
||||
@@ -480,7 +482,7 @@ std::vector<SP<SXCursors>> CXCursorManager::loadStandardCursors(std::string cons
|
||||
|
||||
// load the default xcursor shapes that exist in the theme
|
||||
for (size_t i = 0; i < XCURSOR_STANDARD_NAMES.size(); ++i) {
|
||||
std::string shape{XCURSOR_STANDARD_NAMES[i]};
|
||||
std::string shape{XCURSOR_STANDARD_NAMES.at(i)};
|
||||
auto xImages = XcursorShapeLoadImages(i << 1 /* wtf xcursor? */, name.c_str(), size);
|
||||
|
||||
if (!xImages) {
|
||||
@@ -558,10 +560,6 @@ std::vector<SP<SXCursors>> CXCursorManager::loadAllFromDir(std::string const& pa
|
||||
}
|
||||
|
||||
void CXCursorManager::syncGsettings() {
|
||||
static auto SYNCGSETTINGS = CConfigValue<Hyprlang::INT>("cursor:sync_gsettings_theme");
|
||||
if (!*SYNCGSETTINGS)
|
||||
return;
|
||||
|
||||
auto checkParamExists = [](std::string const& paramName, std::string const& category) {
|
||||
auto* gSettingsSchemaSource = g_settings_schema_source_get_default();
|
||||
|
||||
|
@@ -13,10 +13,10 @@ extern "C" {
|
||||
|
||||
// gangsta bootleg XCursor impl. adidas balkanized
|
||||
struct SXCursorImage {
|
||||
Hyprutils::Math::Vector2D size;
|
||||
Hyprutils::Math::Vector2D hotspot;
|
||||
std::vector<uint32_t> pixels; // XPixel is a u32
|
||||
uint32_t delay; // animation delay to next frame (ms)
|
||||
Vector2D size;
|
||||
Vector2D hotspot;
|
||||
std::vector<uint32_t> pixels; // XPixel is a u32
|
||||
uint32_t delay; // animation delay to next frame (ms)
|
||||
};
|
||||
|
||||
struct SXCursors {
|
||||
|
@@ -55,7 +55,7 @@ void CHyprXWaylandManager::activateWindow(PHLWINDOW pWindow, bool activate) {
|
||||
if (pWindow->m_bIsX11) {
|
||||
|
||||
if (activate) {
|
||||
pWindow->sendWindowSize(true); // update xwayland output pos
|
||||
pWindow->sendWindowSize(pWindow->m_vRealSize->value(), true); // update xwayland output pos
|
||||
pWindow->m_pXWaylandSurface->setMinimized(false);
|
||||
|
||||
if (!pWindow->isX11OverrideRedirect())
|
||||
|
@@ -11,12 +11,11 @@
|
||||
#include <ctime>
|
||||
|
||||
#include <aquamarine/backend/Backend.hpp>
|
||||
using namespace Hyprutils::OS;
|
||||
|
||||
#define TIMESPEC_NSEC_PER_SEC 1000000000L
|
||||
|
||||
CEventLoopManager::CEventLoopManager(wl_display* display, wl_event_loop* wlEventLoop) {
|
||||
m_sTimers.timerfd = CFileDescriptor{timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC)};
|
||||
m_sTimers.timerfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC);
|
||||
m_sWayland.loop = wlEventLoop;
|
||||
m_sWayland.display = display;
|
||||
}
|
||||
@@ -32,6 +31,8 @@ CEventLoopManager::~CEventLoopManager() {
|
||||
wl_event_source_remove(m_sIdle.eventSource);
|
||||
if (m_configWatcherInotifySource)
|
||||
wl_event_source_remove(m_configWatcherInotifySource);
|
||||
if (m_sTimers.timerfd >= 0)
|
||||
close(m_sTimers.timerfd);
|
||||
}
|
||||
|
||||
static int timerWrite(int fd, uint32_t mask, void* data) {
|
||||
@@ -51,10 +52,10 @@ static int configWatcherWrite(int fd, uint32_t mask, void* data) {
|
||||
}
|
||||
|
||||
void CEventLoopManager::enterLoop() {
|
||||
m_sWayland.eventSource = wl_event_loop_add_fd(m_sWayland.loop, m_sTimers.timerfd.get(), WL_EVENT_READABLE, timerWrite, nullptr);
|
||||
m_sWayland.eventSource = wl_event_loop_add_fd(m_sWayland.loop, m_sTimers.timerfd, WL_EVENT_READABLE, timerWrite, nullptr);
|
||||
|
||||
if (const auto& FD = g_pConfigWatcher->getInotifyFD(); FD.isValid())
|
||||
m_configWatcherInotifySource = wl_event_loop_add_fd(m_sWayland.loop, FD.get(), WL_EVENT_READABLE, configWatcherWrite, nullptr);
|
||||
if (const auto FD = g_pConfigWatcher->getInotifyFD(); FD >= 0)
|
||||
m_configWatcherInotifySource = wl_event_loop_add_fd(m_sWayland.loop, FD, WL_EVENT_READABLE, configWatcherWrite, nullptr);
|
||||
|
||||
syncPollFDs();
|
||||
m_sListeners.pollFDsChanged = g_pCompositor->m_pAqBackend->events.pollFDsChanged.registerListener([this](std::any d) { syncPollFDs(); });
|
||||
@@ -119,7 +120,7 @@ void CEventLoopManager::nudgeTimers() {
|
||||
|
||||
itimerspec ts = {.it_value = now};
|
||||
|
||||
timerfd_settime(m_sTimers.timerfd.get(), TFD_TIMER_ABSTIME, &ts, nullptr);
|
||||
timerfd_settime(m_sTimers.timerfd, TFD_TIMER_ABSTIME, &ts, nullptr);
|
||||
}
|
||||
|
||||
void CEventLoopManager::doLater(const std::function<void()>& fn) {
|
||||
|
@@ -6,7 +6,6 @@
|
||||
#include <thread>
|
||||
#include <wayland-server.h>
|
||||
#include "helpers/signal/Signal.hpp"
|
||||
#include <hyprutils/os/FileDescriptor.hpp>
|
||||
|
||||
#include "EventLoopTimer.hpp"
|
||||
|
||||
@@ -55,7 +54,7 @@ class CEventLoopManager {
|
||||
|
||||
struct {
|
||||
std::vector<SP<CEventLoopTimer>> timers;
|
||||
Hyprutils::OS::CFileDescriptor timerfd;
|
||||
int timerfd = -1;
|
||||
} m_sTimers;
|
||||
|
||||
SIdleData m_sIdle;
|
||||
|
@@ -90,30 +90,14 @@ CInputManager::~CInputManager() {
|
||||
void CInputManager::onMouseMoved(IPointer::SMotionEvent e) {
|
||||
static auto PNOACCEL = CConfigValue<Hyprlang::INT>("input:force_no_accel");
|
||||
|
||||
Vector2D delta = e.delta;
|
||||
Vector2D unaccel = e.unaccel;
|
||||
|
||||
if (e.device) {
|
||||
if (e.device->isTouchpad) {
|
||||
if (e.device->flipX) {
|
||||
delta.x = -delta.x;
|
||||
unaccel.x = -unaccel.x;
|
||||
}
|
||||
if (e.device->flipY) {
|
||||
delta.y = -delta.y;
|
||||
unaccel.y = -unaccel.y;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const auto DELTA = *PNOACCEL == 1 ? unaccel : delta;
|
||||
const auto DELTA = *PNOACCEL == 1 ? e.unaccel : e.delta;
|
||||
|
||||
if (g_pSeatManager->isPointerFrameSkipped)
|
||||
g_pPointerManager->storeMovement((uint64_t)e.timeMs, DELTA, unaccel);
|
||||
g_pPointerManager->storeMovement((uint64_t)e.timeMs, DELTA, e.unaccel);
|
||||
else
|
||||
g_pPointerManager->setStoredMovement((uint64_t)e.timeMs, DELTA, unaccel);
|
||||
g_pPointerManager->setStoredMovement((uint64_t)e.timeMs, DELTA, e.unaccel);
|
||||
|
||||
PROTO::relativePointer->sendRelativeMotion((uint64_t)e.timeMs * 1000, DELTA, unaccel);
|
||||
PROTO::relativePointer->sendRelativeMotion((uint64_t)e.timeMs * 1000, DELTA, e.unaccel);
|
||||
|
||||
if (e.mouse)
|
||||
recheckMouseWarpOnMouseInput();
|
||||
@@ -177,23 +161,17 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus, bool mouse) {
|
||||
if (MOUSECOORDSFLOORED == m_vLastCursorPosFloored && !refocus)
|
||||
return;
|
||||
|
||||
static auto PFOLLOWMOUSE = CConfigValue<Hyprlang::INT>("input:follow_mouse");
|
||||
static auto PFOLLOWMOUSETHRESHOLD = CConfigValue<Hyprlang::FLOAT>("input:follow_mouse_threshold");
|
||||
static auto PMOUSEREFOCUS = CConfigValue<Hyprlang::INT>("input:mouse_refocus");
|
||||
static auto PFOLLOWONDND = CConfigValue<Hyprlang::INT>("misc:always_follow_on_dnd");
|
||||
static auto PFLOATBEHAVIOR = CConfigValue<Hyprlang::INT>("input:float_switch_override_focus");
|
||||
static auto PMOUSEFOCUSMON = CConfigValue<Hyprlang::INT>("misc:mouse_move_focuses_monitor");
|
||||
static auto PRESIZEONBORDER = CConfigValue<Hyprlang::INT>("general:resize_on_border");
|
||||
static auto PRESIZECURSORICON = CConfigValue<Hyprlang::INT>("general:hover_icon_on_border");
|
||||
static auto PZOOMFACTOR = CConfigValue<Hyprlang::FLOAT>("cursor:zoom_factor");
|
||||
static auto PFOLLOWMOUSE = CConfigValue<Hyprlang::INT>("input:follow_mouse");
|
||||
static auto PMOUSEREFOCUS = CConfigValue<Hyprlang::INT>("input:mouse_refocus");
|
||||
static auto PFOLLOWONDND = CConfigValue<Hyprlang::INT>("misc:always_follow_on_dnd");
|
||||
static auto PFLOATBEHAVIOR = CConfigValue<Hyprlang::INT>("input:float_switch_override_focus");
|
||||
static auto PMOUSEFOCUSMON = CConfigValue<Hyprlang::INT>("misc:mouse_move_focuses_monitor");
|
||||
static auto PRESIZEONBORDER = CConfigValue<Hyprlang::INT>("general:resize_on_border");
|
||||
static auto PRESIZECURSORICON = CConfigValue<Hyprlang::INT>("general:hover_icon_on_border");
|
||||
static auto PZOOMFACTOR = CConfigValue<Hyprlang::FLOAT>("cursor:zoom_factor");
|
||||
|
||||
const auto FOLLOWMOUSE = *PFOLLOWONDND && PROTO::data->dndActive() ? 1 : *PFOLLOWMOUSE;
|
||||
|
||||
if (FOLLOWMOUSE == 1 && m_tmrLastCursorMovement.getSeconds() < 0.5)
|
||||
m_fMousePosDelta += MOUSECOORDSFLOORED.distance(m_vLastCursorPosFloored);
|
||||
else
|
||||
m_fMousePosDelta = 0;
|
||||
|
||||
m_pFoundSurfaceToFocus.reset();
|
||||
m_pFoundLSToFocus.reset();
|
||||
m_pFoundWindowToFocus.reset();
|
||||
@@ -293,10 +271,9 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus, bool mouse) {
|
||||
const auto BOX = HLSurface->getSurfaceBoxGlobal();
|
||||
|
||||
if (BOX) {
|
||||
const auto PWINDOW = HLSurface->getWindow();
|
||||
surfacePos = BOX->pos();
|
||||
pFoundLayerSurface = HLSurface->getLayer();
|
||||
pFoundWindow = !PWINDOW || PWINDOW->isHidden() ? g_pCompositor->m_pLastWindow.lock() : PWINDOW;
|
||||
pFoundWindow = HLSurface->getWindow();
|
||||
} else // reset foundSurface, find one normally
|
||||
foundSurface = nullptr;
|
||||
} else // reset foundSurface, find one normally
|
||||
@@ -536,10 +513,9 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus, bool mouse) {
|
||||
|
||||
// TODO: this looks wrong. When over a popup, it constantly is switching.
|
||||
// Temp fix until that's figured out. Otherwise spams windowrule lookups and other shit.
|
||||
if (m_pLastMouseFocus.lock() != pFoundWindow || g_pCompositor->m_pLastWindow.lock() != pFoundWindow) {
|
||||
if (m_fMousePosDelta > *PFOLLOWMOUSETHRESHOLD || refocus)
|
||||
g_pCompositor->focusWindow(pFoundWindow, foundSurface);
|
||||
} else
|
||||
if (m_pLastMouseFocus.lock() != pFoundWindow || g_pCompositor->m_pLastWindow.lock() != pFoundWindow)
|
||||
g_pCompositor->focusWindow(pFoundWindow, foundSurface);
|
||||
else
|
||||
g_pCompositor->focusSurface(foundSurface, pFoundWindow);
|
||||
}
|
||||
}
|
||||
@@ -1197,9 +1173,6 @@ void CInputManager::setPointerConfigs() {
|
||||
const auto LIBINPUTSENS = std::clamp(g_pConfigManager->getDeviceFloat(devname, "sensitivity", "input:sensitivity"), -1.f, 1.f);
|
||||
libinput_device_config_accel_set_speed(LIBINPUTDEV, LIBINPUTSENS);
|
||||
|
||||
m->flipX = g_pConfigManager->getDeviceInt(devname, "flip_x", "input:touchpad:flip_x") != 0;
|
||||
m->flipY = g_pConfigManager->getDeviceInt(devname, "flip_y", "input:touchpad:flip_y") != 0;
|
||||
|
||||
const auto ACCELPROFILE = g_pConfigManager->getDeviceString(devname, "accel_profile", "input:accel_profile");
|
||||
const auto SCROLLPOINTS = g_pConfigManager->getDeviceString(devname, "scroll_points", "input:scroll_points");
|
||||
|
||||
@@ -1579,13 +1552,10 @@ void CInputManager::setTouchDeviceConfigs(SP<ITouch> dev) {
|
||||
if (libinput_device_config_send_events_get_mode(LIBINPUTDEV) != mode)
|
||||
libinput_device_config_send_events_set_mode(LIBINPUTDEV, mode);
|
||||
|
||||
if (libinput_device_config_calibration_has_matrix(LIBINPUTDEV)) {
|
||||
Debug::log(LOG, "Setting calibration matrix for device {}", PTOUCHDEV->hlName);
|
||||
// default value of transform being -1 means it's unset.
|
||||
const int ROTATION = std::clamp(g_pConfigManager->getDeviceInt(PTOUCHDEV->hlName, "transform", "input:touchdevice:transform"), -1, 7);
|
||||
if (ROTATION > -1)
|
||||
libinput_device_config_calibration_set_matrix(LIBINPUTDEV, MATRICES[ROTATION]);
|
||||
}
|
||||
const int ROTATION = std::clamp(g_pConfigManager->getDeviceInt(PTOUCHDEV->hlName, "transform", "input:touchdevice:transform"), 0, 7);
|
||||
Debug::log(LOG, "Setting calibration matrix for device {}", PTOUCHDEV->hlName);
|
||||
if (libinput_device_config_calibration_has_matrix(LIBINPUTDEV))
|
||||
libinput_device_config_calibration_set_matrix(LIBINPUTDEV, MATRICES[ROTATION]);
|
||||
|
||||
auto output = g_pConfigManager->getDeviceString(PTOUCHDEV->hlName, "output", "input:touchdevice:output");
|
||||
bool bound = !output.empty() && output != STRVAL_EMPTY;
|
||||
@@ -1627,10 +1597,9 @@ void CInputManager::setTabletConfigs() {
|
||||
const auto RELINPUT = g_pConfigManager->getDeviceInt(NAME, "relative_input", "input:tablet:relative_input");
|
||||
t->relativeInput = RELINPUT;
|
||||
|
||||
const int ROTATION = std::clamp(g_pConfigManager->getDeviceInt(NAME, "transform", "input:tablet:transform"), -1, 7);
|
||||
const int ROTATION = std::clamp(g_pConfigManager->getDeviceInt(NAME, "transform", "input:tablet:transform"), 0, 7);
|
||||
Debug::log(LOG, "Setting calibration matrix for device {}", NAME);
|
||||
if (ROTATION > -1)
|
||||
libinput_device_config_calibration_set_matrix(LIBINPUTDEV, MATRICES[ROTATION]);
|
||||
libinput_device_config_calibration_set_matrix(LIBINPUTDEV, MATRICES[ROTATION]);
|
||||
|
||||
if (g_pConfigManager->getDeviceInt(NAME, "left_handed", "input:tablet:left_handed") == 0)
|
||||
libinput_device_config_left_handed_set(LIBINPUTDEV, 0);
|
||||
@@ -1731,11 +1700,8 @@ void CInputManager::releaseAllMouseButtons() {
|
||||
if (PROTO::data->dndActive())
|
||||
return;
|
||||
|
||||
timespec now;
|
||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||
|
||||
for (auto const& mb : buttonsCopy) {
|
||||
g_pSeatManager->sendPointerButton(now.tv_sec * 1000 + now.tv_nsec / 1000000, mb, WL_POINTER_BUTTON_STATE_RELEASED);
|
||||
g_pSeatManager->sendPointerButton(0, mb, WL_POINTER_BUTTON_STATE_RELEASED);
|
||||
}
|
||||
|
||||
m_lCurrentlyHeldButtons.clear();
|
||||
|
@@ -255,7 +255,6 @@ class CInputManager {
|
||||
|
||||
// used for warping back after non-mouse input
|
||||
Vector2D m_vLastMousePos = {};
|
||||
double m_fMousePosDelta = 0;
|
||||
bool m_bLastInputMouse = true;
|
||||
|
||||
// for holding focus on buttons held
|
||||
|
@@ -88,20 +88,6 @@ static void refocusTablet(SP<CTablet> tab, SP<CTabletTool> tool, bool motion = f
|
||||
PROTO::tablet->motion(tool, local);
|
||||
}
|
||||
|
||||
static Vector2D transformToActiveRegion(const Vector2D pos, const CBox activeArea) {
|
||||
auto newPos = pos;
|
||||
|
||||
//Calculate transformations if active area is set
|
||||
if (!activeArea.empty()) {
|
||||
if (!std::isnan(pos.x))
|
||||
newPos.x = (pos.x - activeArea.x) / (activeArea.w - activeArea.x);
|
||||
if (!std::isnan(pos.y))
|
||||
newPos.y = (pos.y - activeArea.y) / (activeArea.h - activeArea.y);
|
||||
}
|
||||
|
||||
return newPos;
|
||||
}
|
||||
|
||||
void CInputManager::onTabletAxis(CTablet::SAxisEvent e) {
|
||||
const auto PTAB = e.tablet;
|
||||
const auto PTOOL = ensureTabletToolPresent(e.tool);
|
||||
@@ -127,9 +113,16 @@ void CInputManager::onTabletAxis(CTablet::SAxisEvent e) {
|
||||
|
||||
if (PTAB->relativeInput)
|
||||
g_pPointerManager->move(delta);
|
||||
else
|
||||
g_pPointerManager->warpAbsolute(transformToActiveRegion({x, y}, PTAB->activeArea), PTAB);
|
||||
|
||||
else {
|
||||
//Calculate transformations if active area is set
|
||||
if (!PTAB->activeArea.empty()) {
|
||||
if (!std::isnan(x))
|
||||
x = (x - PTAB->activeArea.x) / (PTAB->activeArea.w - PTAB->activeArea.x);
|
||||
if (!std::isnan(y))
|
||||
y = (y - PTAB->activeArea.y) / (PTAB->activeArea.h - PTAB->activeArea.y);
|
||||
}
|
||||
g_pPointerManager->warpAbsolute({x, y}, PTAB);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -167,12 +160,7 @@ void CInputManager::onTabletTip(CTablet::STipEvent e) {
|
||||
const auto PTAB = e.tablet;
|
||||
const auto PTOOL = ensureTabletToolPresent(e.tool);
|
||||
const auto POS = e.tip;
|
||||
|
||||
if (PTAB->relativeInput)
|
||||
g_pPointerManager->move({0, 0});
|
||||
else
|
||||
g_pPointerManager->warpAbsolute(transformToActiveRegion(POS, PTAB->activeArea), PTAB);
|
||||
|
||||
g_pPointerManager->warpAbsolute(POS, PTAB);
|
||||
refocusTablet(PTAB, PTOOL, true);
|
||||
|
||||
if (e.in)
|
||||
|
@@ -41,7 +41,7 @@ void CInputManager::onTouchDown(ITouch::SDownEvent e) {
|
||||
if (m_sActiveSwipe.pWorkspaceBegin) {
|
||||
return;
|
||||
// TODO: Don't swipe if you touched a floating window.
|
||||
} else if (*PSWIPETOUCH && (m_pFoundLSToFocus.expired() || m_pFoundLSToFocus->layer <= 1) && !g_pSessionLockManager->isSessionLocked()) {
|
||||
} else if (*PSWIPETOUCH && (m_pFoundLSToFocus.expired() || m_pFoundLSToFocus->layer <= 1)) {
|
||||
const auto PWORKSPACE = PMONITOR->activeWorkspace;
|
||||
const auto STYLE = PWORKSPACE->m_vRenderOffset->getStyle();
|
||||
const bool VERTANIMS = STYLE == "slidevert" || STYLE.starts_with("slidefadevert");
|
||||
|
@@ -59,13 +59,6 @@ struct SVersionInfo {
|
||||
#define OPTIONAL
|
||||
#define HANDLE void*
|
||||
|
||||
// C ABI is needed to prevent symbol mangling, but we don't actually need C compatibility,
|
||||
// so we ignore this warning about return types that are potentially incompatible with C.
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wreturn-type-c-linkage"
|
||||
#endif
|
||||
|
||||
class IHyprLayout;
|
||||
class CWindow;
|
||||
class IHyprWindowDecoration;
|
||||
@@ -77,7 +70,7 @@ class CWindow;
|
||||
Methods marked with REQUIRED are required.
|
||||
*/
|
||||
|
||||
/*
|
||||
/*
|
||||
called pre-plugin init.
|
||||
In case of a version mismatch, will eject the .so.
|
||||
|
||||
@@ -322,7 +315,3 @@ APICALL inline EXPORT const char* __hyprland_api_get_client_hash() {
|
||||
return GIT_COMMIT_HASH;
|
||||
}
|
||||
// NOLINTEND
|
||||
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
|
@@ -15,9 +15,6 @@ CHyprlandCTMControlResource::CHyprlandCTMControlResource(SP<CHyprlandCtmControlM
|
||||
|
||||
resource->setSetCtmForOutput([this](CHyprlandCtmControlManagerV1* r, wl_resource* output, wl_fixed_t mat0, wl_fixed_t mat1, wl_fixed_t mat2, wl_fixed_t mat3, wl_fixed_t mat4,
|
||||
wl_fixed_t mat5, wl_fixed_t mat6, wl_fixed_t mat7, wl_fixed_t mat8) {
|
||||
if (blocked)
|
||||
return;
|
||||
|
||||
const auto OUTPUTRESOURCE = CWLOutputResource::fromResource(output);
|
||||
|
||||
if UNLIKELY (!OUTPUTRESOURCE)
|
||||
@@ -44,9 +41,6 @@ CHyprlandCTMControlResource::CHyprlandCTMControlResource(SP<CHyprlandCtmControlM
|
||||
});
|
||||
|
||||
resource->setCommit([this](CHyprlandCtmControlManagerV1* r) {
|
||||
if (blocked)
|
||||
return;
|
||||
|
||||
LOGM(LOG, "Committing ctms to outputs");
|
||||
|
||||
for (auto& m : g_pCompositor->m_vMonitors) {
|
||||
@@ -60,17 +54,7 @@ CHyprlandCTMControlResource::CHyprlandCTMControlResource(SP<CHyprlandCtmControlM
|
||||
});
|
||||
}
|
||||
|
||||
void CHyprlandCTMControlResource::block() {
|
||||
blocked = true;
|
||||
|
||||
if (resource->version() >= 2)
|
||||
resource->sendBlocked();
|
||||
}
|
||||
|
||||
CHyprlandCTMControlResource::~CHyprlandCTMControlResource() {
|
||||
if (blocked)
|
||||
return;
|
||||
|
||||
for (auto& m : g_pCompositor->m_vMonitors) {
|
||||
PROTO::ctm->setCTM(m, Mat3x3::identity());
|
||||
}
|
||||
@@ -85,6 +69,7 @@ CHyprlandCTMControlProtocol::CHyprlandCTMControlProtocol(const wl_interface* ifa
|
||||
}
|
||||
|
||||
void CHyprlandCTMControlProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) {
|
||||
|
||||
const auto RESOURCE = m_vManagers.emplace_back(makeShared<CHyprlandCTMControlResource>(makeShared<CHyprlandCtmControlManagerV1>(client, ver, id)));
|
||||
|
||||
if UNLIKELY (!RESOURCE->good()) {
|
||||
@@ -93,11 +78,6 @@ void CHyprlandCTMControlProtocol::bindManager(wl_client* client, void* data, uin
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_pManager)
|
||||
RESOURCE->block();
|
||||
else
|
||||
m_pManager = RESOURCE;
|
||||
|
||||
LOGM(LOG, "New CTM Manager at 0x{:x}", (uintptr_t)RESOURCE.get());
|
||||
}
|
||||
|
||||
|
@@ -16,13 +16,11 @@ class CHyprlandCTMControlResource {
|
||||
~CHyprlandCTMControlResource();
|
||||
|
||||
bool good();
|
||||
void block();
|
||||
|
||||
private:
|
||||
SP<CHyprlandCtmControlManagerV1> resource;
|
||||
|
||||
std::unordered_map<std::string, Mat3x3> ctms;
|
||||
bool blocked = false;
|
||||
};
|
||||
|
||||
class CHyprlandCTMControlProtocol : public IWaylandProtocol {
|
||||
@@ -39,7 +37,6 @@ class CHyprlandCTMControlProtocol : public IWaylandProtocol {
|
||||
|
||||
//
|
||||
std::vector<SP<CHyprlandCTMControlResource>> m_vManagers;
|
||||
WP<CHyprlandCTMControlResource> m_pManager;
|
||||
|
||||
//
|
||||
struct SCTMData {
|
||||
@@ -54,4 +51,4 @@ class CHyprlandCTMControlProtocol : public IWaylandProtocol {
|
||||
|
||||
namespace PROTO {
|
||||
inline UP<CHyprlandCTMControlProtocol> ctm;
|
||||
};
|
||||
};
|
@@ -1,90 +1,42 @@
|
||||
#include "ColorManagement.hpp"
|
||||
#include "Compositor.hpp"
|
||||
#include "color-management-v1.hpp"
|
||||
#include "../helpers/Monitor.hpp"
|
||||
#include "core/Output.hpp"
|
||||
#include "types/ColorManagement.hpp"
|
||||
#include <cstdint>
|
||||
|
||||
using namespace NColorManagement;
|
||||
|
||||
static uint64_t lastImageID = 0; // FIXME use for deduplication
|
||||
|
||||
CColorManager::CColorManager(SP<CWpColorManagerV1> resource) : m_resource(resource) {
|
||||
CColorManager::CColorManager(SP<CXxColorManagerV4> resource_) : resource(resource_) {
|
||||
if UNLIKELY (!good())
|
||||
return;
|
||||
|
||||
m_resource->sendSupportedFeature(WP_COLOR_MANAGER_V1_FEATURE_PARAMETRIC);
|
||||
m_resource->sendSupportedFeature(WP_COLOR_MANAGER_V1_FEATURE_SET_PRIMARIES);
|
||||
m_resource->sendSupportedFeature(WP_COLOR_MANAGER_V1_FEATURE_SET_LUMINANCES);
|
||||
resource->sendSupportedFeature(XX_COLOR_MANAGER_V4_FEATURE_PARAMETRIC);
|
||||
resource->sendSupportedFeature(XX_COLOR_MANAGER_V4_FEATURE_EXTENDED_TARGET_VOLUME);
|
||||
resource->sendSupportedFeature(XX_COLOR_MANAGER_V4_FEATURE_SET_MASTERING_DISPLAY_PRIMARIES);
|
||||
resource->sendSupportedFeature(XX_COLOR_MANAGER_V4_FEATURE_SET_PRIMARIES);
|
||||
resource->sendSupportedFeature(XX_COLOR_MANAGER_V4_FEATURE_SET_LUMINANCES);
|
||||
|
||||
if (PROTO::colorManagement->m_debug) {
|
||||
m_resource->sendSupportedFeature(WP_COLOR_MANAGER_V1_FEATURE_ICC_V2_V4);
|
||||
m_resource->sendSupportedFeature(WP_COLOR_MANAGER_V1_FEATURE_SET_TF_POWER);
|
||||
m_resource->sendSupportedFeature(WP_COLOR_MANAGER_V1_FEATURE_SET_MASTERING_DISPLAY_PRIMARIES);
|
||||
m_resource->sendSupportedFeature(WP_COLOR_MANAGER_V1_FEATURE_EXTENDED_TARGET_VOLUME);
|
||||
m_resource->sendSupportedFeature(WP_COLOR_MANAGER_V1_FEATURE_WINDOWS_SCRGB);
|
||||
}
|
||||
resource->sendSupportedPrimariesNamed(XX_COLOR_MANAGER_V4_PRIMARIES_SRGB);
|
||||
// resource->sendSupportedPrimariesNamed(XX_COLOR_MANAGER_V4_PRIMARIES_PAL_M);
|
||||
// resource->sendSupportedPrimariesNamed(XX_COLOR_MANAGER_V4_PRIMARIES_PAL);
|
||||
// resource->sendSupportedPrimariesNamed(XX_COLOR_MANAGER_V4_PRIMARIES_NTSC);
|
||||
// resource->sendSupportedPrimariesNamed(XX_COLOR_MANAGER_V4_PRIMARIES_GENERIC_FILM);
|
||||
resource->sendSupportedPrimariesNamed(XX_COLOR_MANAGER_V4_PRIMARIES_BT2020);
|
||||
// resource->sendSupportedPrimariesNamed(XX_COLOR_MANAGER_V4_PRIMARIES_CIE1931_XYZ);
|
||||
// resource->sendSupportedPrimariesNamed(XX_COLOR_MANAGER_V4_PRIMARIES_DCI_P3);
|
||||
// resource->sendSupportedPrimariesNamed(XX_COLOR_MANAGER_V4_PRIMARIES_DISPLAY_P3);
|
||||
// resource->sendSupportedPrimariesNamed(XX_COLOR_MANAGER_V4_PRIMARIES_ADOBE_RGB);
|
||||
|
||||
m_resource->sendSupportedPrimariesNamed(WP_COLOR_MANAGER_V1_PRIMARIES_SRGB);
|
||||
m_resource->sendSupportedPrimariesNamed(WP_COLOR_MANAGER_V1_PRIMARIES_BT2020);
|
||||
m_resource->sendSupportedPrimariesNamed(WP_COLOR_MANAGER_V1_PRIMARIES_PAL_M);
|
||||
m_resource->sendSupportedPrimariesNamed(WP_COLOR_MANAGER_V1_PRIMARIES_PAL);
|
||||
m_resource->sendSupportedPrimariesNamed(WP_COLOR_MANAGER_V1_PRIMARIES_NTSC);
|
||||
m_resource->sendSupportedPrimariesNamed(WP_COLOR_MANAGER_V1_PRIMARIES_GENERIC_FILM);
|
||||
m_resource->sendSupportedPrimariesNamed(WP_COLOR_MANAGER_V1_PRIMARIES_DCI_P3);
|
||||
m_resource->sendSupportedPrimariesNamed(WP_COLOR_MANAGER_V1_PRIMARIES_DISPLAY_P3);
|
||||
m_resource->sendSupportedPrimariesNamed(WP_COLOR_MANAGER_V1_PRIMARIES_ADOBE_RGB);
|
||||
// resource->sendSupportedTfNamed(XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_GAMMA22);
|
||||
resource->sendSupportedTfNamed(XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_SRGB);
|
||||
resource->sendSupportedTfNamed(XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_ST2084_PQ);
|
||||
// resource->sendSupportedTfNamed(XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_LINEAR);
|
||||
|
||||
if (PROTO::colorManagement->m_debug) {
|
||||
m_resource->sendSupportedPrimariesNamed(WP_COLOR_MANAGER_V1_PRIMARIES_CIE1931_XYZ);
|
||||
}
|
||||
resource->sendSupportedIntent(XX_COLOR_MANAGER_V4_RENDER_INTENT_PERCEPTUAL);
|
||||
// resource->sendSupportedIntent(XX_COLOR_MANAGER_V4_RENDER_INTENT_RELATIVE);
|
||||
// resource->sendSupportedIntent(XX_COLOR_MANAGER_V4_RENDER_INTENT_ABSOLUTE);
|
||||
// resource->sendSupportedIntent(XX_COLOR_MANAGER_V4_RENDER_INTENT_RELATIVE_BPC);
|
||||
|
||||
m_resource->sendSupportedTfNamed(WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_SRGB);
|
||||
m_resource->sendSupportedTfNamed(WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_GAMMA22);
|
||||
m_resource->sendSupportedTfNamed(WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_GAMMA28);
|
||||
m_resource->sendSupportedTfNamed(WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_EXT_LINEAR);
|
||||
m_resource->sendSupportedTfNamed(WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_ST2084_PQ);
|
||||
m_resource->sendSupportedTfNamed(WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_HLG);
|
||||
|
||||
if (PROTO::colorManagement->m_debug) {
|
||||
m_resource->sendSupportedTfNamed(WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_BT1886);
|
||||
m_resource->sendSupportedTfNamed(WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_ST240);
|
||||
m_resource->sendSupportedTfNamed(WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_LOG_100);
|
||||
m_resource->sendSupportedTfNamed(WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_LOG_316);
|
||||
m_resource->sendSupportedTfNamed(WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_XVYCC);
|
||||
m_resource->sendSupportedTfNamed(WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_EXT_SRGB);
|
||||
m_resource->sendSupportedTfNamed(WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_ST428);
|
||||
}
|
||||
|
||||
m_resource->sendSupportedIntent(WP_COLOR_MANAGER_V1_RENDER_INTENT_PERCEPTUAL);
|
||||
if (PROTO::colorManagement->m_debug) {
|
||||
m_resource->sendSupportedIntent(WP_COLOR_MANAGER_V1_RENDER_INTENT_RELATIVE);
|
||||
m_resource->sendSupportedIntent(WP_COLOR_MANAGER_V1_RENDER_INTENT_SATURATION);
|
||||
m_resource->sendSupportedIntent(WP_COLOR_MANAGER_V1_RENDER_INTENT_ABSOLUTE);
|
||||
m_resource->sendSupportedIntent(WP_COLOR_MANAGER_V1_RENDER_INTENT_RELATIVE_BPC);
|
||||
}
|
||||
|
||||
m_resource->setDestroy([](CWpColorManagerV1* r) { LOGM(TRACE, "Destroy WP_color_manager at {:x} (generated default)", (uintptr_t)r); });
|
||||
m_resource->setGetOutput([](CWpColorManagerV1* r, uint32_t id, wl_resource* output) {
|
||||
resource->setDestroy([](CXxColorManagerV4* r) { LOGM(TRACE, "Destroy xx_color_manager at {:x} (generated default)", (uintptr_t)r); });
|
||||
resource->setGetOutput([](CXxColorManagerV4* r, uint32_t id, wl_resource* output) {
|
||||
LOGM(TRACE, "Get output for id={}, output={}", id, (uintptr_t)output);
|
||||
|
||||
const auto OUTPUTRESOURCE = CWLOutputResource::fromResource(output);
|
||||
|
||||
if UNLIKELY (!OUTPUTRESOURCE) {
|
||||
r->error(-1, "Invalid output (2)");
|
||||
return;
|
||||
}
|
||||
|
||||
const auto PMONITOR = OUTPUTRESOURCE->monitor.lock();
|
||||
|
||||
if UNLIKELY (!PMONITOR) {
|
||||
r->error(-1, "Invalid output (2)");
|
||||
return;
|
||||
}
|
||||
|
||||
const auto RESOURCE =
|
||||
PROTO::colorManagement->m_vOutputs.emplace_back(makeShared<CColorManagementOutput>(makeShared<CWpColorManagementOutputV1>(r->client(), r->version(), id), PMONITOR));
|
||||
PROTO::colorManagement->m_vOutputs.emplace_back(makeShared<CColorManagementOutput>(makeShared<CXxColorManagementOutputV4>(r->client(), r->version(), id)));
|
||||
|
||||
if UNLIKELY (!RESOURCE->good()) {
|
||||
r->noMemory();
|
||||
@@ -94,7 +46,7 @@ CColorManager::CColorManager(SP<CWpColorManagerV1> resource) : m_resource(resour
|
||||
|
||||
RESOURCE->self = RESOURCE;
|
||||
});
|
||||
m_resource->setGetSurface([](CWpColorManagerV1* r, uint32_t id, wl_resource* surface) {
|
||||
resource->setGetSurface([](CXxColorManagerV4* r, uint32_t id, wl_resource* surface) {
|
||||
LOGM(TRACE, "Get surface for id={}, surface={}", id, (uintptr_t)surface);
|
||||
auto SURF = CWLSurfaceResource::fromResource(surface);
|
||||
|
||||
@@ -105,12 +57,12 @@ CColorManager::CColorManager(SP<CWpColorManagerV1> resource) : m_resource(resour
|
||||
}
|
||||
|
||||
if (SURF->colorManagement) {
|
||||
r->error(WP_COLOR_MANAGER_V1_ERROR_SURFACE_EXISTS, "CM Surface already exists");
|
||||
r->error(XX_COLOR_MANAGER_V4_ERROR_SURFACE_EXISTS, "CM Surface already exists");
|
||||
return;
|
||||
}
|
||||
|
||||
const auto RESOURCE =
|
||||
PROTO::colorManagement->m_vSurfaces.emplace_back(makeShared<CColorManagementSurface>(makeShared<CWpColorManagementSurfaceV1>(r->client(), r->version(), id), SURF));
|
||||
PROTO::colorManagement->m_vSurfaces.emplace_back(makeShared<CColorManagementSurface>(makeShared<CXxColorManagementSurfaceV4>(r->client(), r->version(), id), SURF));
|
||||
if UNLIKELY (!RESOURCE->good()) {
|
||||
r->noMemory();
|
||||
PROTO::colorManagement->m_vSurfaces.pop_back();
|
||||
@@ -121,7 +73,7 @@ CColorManager::CColorManager(SP<CWpColorManagerV1> resource) : m_resource(resour
|
||||
|
||||
SURF->colorManagement = RESOURCE;
|
||||
});
|
||||
m_resource->setGetSurfaceFeedback([](CWpColorManagerV1* r, uint32_t id, wl_resource* surface) {
|
||||
resource->setGetFeedbackSurface([](CXxColorManagerV4* r, uint32_t id, wl_resource* surface) {
|
||||
LOGM(TRACE, "Get feedback surface for id={}, surface={}", id, (uintptr_t)surface);
|
||||
auto SURF = CWLSurfaceResource::fromResource(surface);
|
||||
|
||||
@@ -132,7 +84,7 @@ CColorManager::CColorManager(SP<CWpColorManagerV1> resource) : m_resource(resour
|
||||
}
|
||||
|
||||
const auto RESOURCE = PROTO::colorManagement->m_vFeedbackSurfaces.emplace_back(
|
||||
makeShared<CColorManagementFeedbackSurface>(makeShared<CWpColorManagementSurfaceFeedbackV1>(r->client(), r->version(), id), SURF));
|
||||
makeShared<CColorManagementFeedbackSurface>(makeShared<CXxColorManagementFeedbackSurfaceV4>(r->client(), r->version(), id), SURF));
|
||||
|
||||
if UNLIKELY (!RESOURCE->good()) {
|
||||
r->noMemory();
|
||||
@@ -142,29 +94,15 @@ CColorManager::CColorManager(SP<CWpColorManagerV1> resource) : m_resource(resour
|
||||
|
||||
RESOURCE->self = RESOURCE;
|
||||
});
|
||||
m_resource->setCreateIccCreator([](CWpColorManagerV1* r, uint32_t id) {
|
||||
resource->setNewIccCreator([](CXxColorManagerV4* r, uint32_t id) {
|
||||
LOGM(WARN, "New ICC creator for id={} (unsupported)", id);
|
||||
if (!PROTO::colorManagement->m_debug) {
|
||||
r->error(WP_COLOR_MANAGER_V1_ERROR_UNSUPPORTED_FEATURE, "ICC profiles are not supported");
|
||||
return;
|
||||
}
|
||||
|
||||
const auto RESOURCE =
|
||||
PROTO::colorManagement->m_vIccCreators.emplace_back(makeShared<CColorManagementIccCreator>(makeShared<CWpImageDescriptionCreatorIccV1>(r->client(), r->version(), id)));
|
||||
|
||||
if UNLIKELY (!RESOURCE->good()) {
|
||||
r->noMemory();
|
||||
PROTO::colorManagement->m_vIccCreators.pop_back();
|
||||
return;
|
||||
}
|
||||
|
||||
RESOURCE->self = RESOURCE;
|
||||
r->error(XX_COLOR_MANAGER_V4_ERROR_UNSUPPORTED_FEATURE, "ICC profiles are not supported");
|
||||
});
|
||||
m_resource->setCreateParametricCreator([](CWpColorManagerV1* r, uint32_t id) {
|
||||
resource->setNewParametricCreator([](CXxColorManagerV4* r, uint32_t id) {
|
||||
LOGM(TRACE, "New parametric creator for id={}", id);
|
||||
|
||||
const auto RESOURCE = PROTO::colorManagement->m_vParametricCreators.emplace_back(
|
||||
makeShared<CColorManagementParametricCreator>(makeShared<CWpImageDescriptionCreatorParamsV1>(r->client(), r->version(), id)));
|
||||
makeShared<CColorManagementParametricCreator>(makeShared<CXxImageDescriptionCreatorParamsV4>(r->client(), r->version(), id)));
|
||||
|
||||
if UNLIKELY (!RESOURCE->good()) {
|
||||
r->noMemory();
|
||||
@@ -174,59 +112,30 @@ CColorManager::CColorManager(SP<CWpColorManagerV1> resource) : m_resource(resour
|
||||
|
||||
RESOURCE->self = RESOURCE;
|
||||
});
|
||||
m_resource->setCreateWindowsScrgb([](CWpColorManagerV1* r, uint32_t id) {
|
||||
LOGM(WARN, "New Windows scRGB description id={} (unsupported)", id);
|
||||
if (!PROTO::colorManagement->m_debug) {
|
||||
r->error(WP_COLOR_MANAGER_V1_ERROR_UNSUPPORTED_FEATURE, "Windows scRGB profiles are not supported");
|
||||
return;
|
||||
}
|
||||
|
||||
const auto RESOURCE = PROTO::colorManagement->m_vImageDescriptions.emplace_back(
|
||||
makeShared<CColorManagementImageDescription>(makeShared<CWpImageDescriptionV1>(r->client(), r->version(), id), false));
|
||||
|
||||
if UNLIKELY (!RESOURCE->good()) {
|
||||
r->noMemory();
|
||||
PROTO::colorManagement->m_vImageDescriptions.pop_back();
|
||||
return;
|
||||
}
|
||||
|
||||
RESOURCE->self = RESOURCE;
|
||||
RESOURCE->settings.id = ++lastImageID;
|
||||
RESOURCE->settings.windowsScRGB = true;
|
||||
RESOURCE->settings.primariesNamed = NColorManagement::CM_PRIMARIES_SRGB;
|
||||
RESOURCE->settings.primariesNameSet = true;
|
||||
RESOURCE->settings.primaries = NColorPrimaries::BT709;
|
||||
RESOURCE->settings.transferFunction = NColorManagement::CM_TRANSFER_FUNCTION_EXT_LINEAR;
|
||||
RESOURCE->settings.luminances.reference = 203;
|
||||
RESOURCE->resource()->sendReady(RESOURCE->settings.id);
|
||||
});
|
||||
|
||||
m_resource->setOnDestroy([this](CWpColorManagerV1* r) { PROTO::colorManagement->destroyResource(this); });
|
||||
|
||||
m_resource->sendDone();
|
||||
resource->setOnDestroy([this](CXxColorManagerV4* r) { PROTO::colorManagement->destroyResource(this); });
|
||||
}
|
||||
|
||||
bool CColorManager::good() {
|
||||
return m_resource->resource();
|
||||
return resource->resource();
|
||||
}
|
||||
|
||||
CColorManagementOutput::CColorManagementOutput(SP<CWpColorManagementOutputV1> resource, WP<CMonitor> monitor) : m_resource(resource), m_monitor(monitor) {
|
||||
CColorManagementOutput::CColorManagementOutput(SP<CXxColorManagementOutputV4> resource_) : resource(resource_) {
|
||||
if UNLIKELY (!good())
|
||||
return;
|
||||
|
||||
pClient = m_resource->client();
|
||||
pClient = resource->client();
|
||||
|
||||
m_resource->setDestroy([this](CWpColorManagementOutputV1* r) { PROTO::colorManagement->destroyResource(this); });
|
||||
m_resource->setOnDestroy([this](CWpColorManagementOutputV1* r) { PROTO::colorManagement->destroyResource(this); });
|
||||
resource->setDestroy([this](CXxColorManagementOutputV4* r) { PROTO::colorManagement->destroyResource(this); });
|
||||
resource->setOnDestroy([this](CXxColorManagementOutputV4* r) { PROTO::colorManagement->destroyResource(this); });
|
||||
|
||||
m_resource->setGetImageDescription([this](CWpColorManagementOutputV1* r, uint32_t id) {
|
||||
resource->setGetImageDescription([this](CXxColorManagementOutputV4* r, uint32_t id) {
|
||||
LOGM(TRACE, "Get image description for output={}, id={}", (uintptr_t)r, id);
|
||||
|
||||
if (imageDescription.valid())
|
||||
PROTO::colorManagement->destroyResource(imageDescription.get());
|
||||
|
||||
const auto RESOURCE = PROTO::colorManagement->m_vImageDescriptions.emplace_back(
|
||||
makeShared<CColorManagementImageDescription>(makeShared<CWpImageDescriptionV1>(r->client(), r->version(), id), true));
|
||||
makeShared<CColorManagementImageDescription>(makeShared<CXxImageDescriptionV4>(r->client(), r->version(), id)));
|
||||
|
||||
if UNLIKELY (!RESOURCE->good()) {
|
||||
r->noMemory();
|
||||
@@ -235,19 +144,11 @@ CColorManagementOutput::CColorManagementOutput(SP<CWpColorManagementOutputV1> re
|
||||
}
|
||||
|
||||
RESOURCE->self = RESOURCE;
|
||||
if (!m_monitor.valid())
|
||||
RESOURCE->m_resource->sendFailed(WP_IMAGE_DESCRIPTION_V1_CAUSE_NO_OUTPUT, "No output");
|
||||
else {
|
||||
RESOURCE->settings = m_monitor->imageDescription;
|
||||
if (RESOURCE->settings.id)
|
||||
RESOURCE->settings.id = ++lastImageID;
|
||||
RESOURCE->m_resource->sendReady(RESOURCE->settings.id); // FIXME: create correct id
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
bool CColorManagementOutput::good() {
|
||||
return m_resource->resource();
|
||||
return resource->resource();
|
||||
}
|
||||
|
||||
wl_client* CColorManagementOutput::client() {
|
||||
@@ -258,45 +159,45 @@ CColorManagementSurface::CColorManagementSurface(SP<CWLSurfaceResource> surface_
|
||||
// only for frog cm untill wayland cm is adopted
|
||||
}
|
||||
|
||||
CColorManagementSurface::CColorManagementSurface(SP<CWpColorManagementSurfaceV1> resource, SP<CWLSurfaceResource> surface_) : surface(surface_), m_resource(resource) {
|
||||
CColorManagementSurface::CColorManagementSurface(SP<CXxColorManagementSurfaceV4> resource_, SP<CWLSurfaceResource> surface_) : surface(surface_), resource(resource_) {
|
||||
if UNLIKELY (!good())
|
||||
return;
|
||||
|
||||
pClient = m_resource->client();
|
||||
pClient = resource->client();
|
||||
|
||||
m_resource->setDestroy([this](CWpColorManagementSurfaceV1* r) {
|
||||
resource->setDestroy([this](CXxColorManagementSurfaceV4* r) {
|
||||
LOGM(TRACE, "Destroy xx cm surface {}", (uintptr_t)surface);
|
||||
PROTO::colorManagement->destroyResource(this);
|
||||
});
|
||||
m_resource->setOnDestroy([this](CWpColorManagementSurfaceV1* r) {
|
||||
resource->setOnDestroy([this](CXxColorManagementSurfaceV4* r) {
|
||||
LOGM(TRACE, "Destroy xx cm surface {}", (uintptr_t)surface);
|
||||
PROTO::colorManagement->destroyResource(this);
|
||||
});
|
||||
|
||||
m_resource->setSetImageDescription([this](CWpColorManagementSurfaceV1* r, wl_resource* image_description, uint32_t render_intent) {
|
||||
resource->setSetImageDescription([this](CXxColorManagementSurfaceV4* r, wl_resource* image_description, uint32_t render_intent) {
|
||||
LOGM(TRACE, "Set image description for surface={}, desc={}, intent={}", (uintptr_t)r, (uintptr_t)image_description, render_intent);
|
||||
|
||||
const auto PO = (CWpImageDescriptionV1*)wl_resource_get_user_data(image_description);
|
||||
const auto PO = (CXxImageDescriptionV4*)wl_resource_get_user_data(image_description);
|
||||
if (!PO) { // FIXME check validity
|
||||
r->error(WP_COLOR_MANAGEMENT_SURFACE_V1_ERROR_IMAGE_DESCRIPTION, "Image description creation failed");
|
||||
r->error(XX_COLOR_MANAGEMENT_SURFACE_V4_ERROR_IMAGE_DESCRIPTION, "Image description creation failed");
|
||||
return;
|
||||
}
|
||||
if (render_intent != WP_COLOR_MANAGER_V1_RENDER_INTENT_PERCEPTUAL) {
|
||||
r->error(WP_COLOR_MANAGEMENT_SURFACE_V1_ERROR_RENDER_INTENT, "Unsupported render intent");
|
||||
if (render_intent != XX_COLOR_MANAGER_V4_RENDER_INTENT_PERCEPTUAL) {
|
||||
r->error(XX_COLOR_MANAGEMENT_SURFACE_V4_ERROR_RENDER_INTENT, "Unsupported render intent");
|
||||
return;
|
||||
}
|
||||
|
||||
const auto imageDescription = std::find_if(PROTO::colorManagement->m_vImageDescriptions.begin(), PROTO::colorManagement->m_vImageDescriptions.end(),
|
||||
[&](const auto& other) { return other->resource()->resource() == image_description; });
|
||||
if (imageDescription == PROTO::colorManagement->m_vImageDescriptions.end()) {
|
||||
r->error(WP_COLOR_MANAGEMENT_SURFACE_V1_ERROR_IMAGE_DESCRIPTION, "Image description not found");
|
||||
r->error(XX_COLOR_MANAGEMENT_SURFACE_V4_ERROR_IMAGE_DESCRIPTION, "Image description not found");
|
||||
return;
|
||||
}
|
||||
|
||||
setHasImageDescription(true);
|
||||
m_imageDescription = imageDescription->get()->settings;
|
||||
});
|
||||
m_resource->setUnsetImageDescription([this](CWpColorManagementSurfaceV1* r) {
|
||||
resource->setUnsetImageDescription([this](CXxColorManagementSurfaceV4* r) {
|
||||
LOGM(TRACE, "Unset image description for surface={}", (uintptr_t)r);
|
||||
m_imageDescription = SImageDescription{};
|
||||
setHasImageDescription(false);
|
||||
@@ -304,7 +205,7 @@ CColorManagementSurface::CColorManagementSurface(SP<CWpColorManagementSurfaceV1>
|
||||
}
|
||||
|
||||
bool CColorManagementSurface::good() {
|
||||
return m_resource && m_resource->resource();
|
||||
return resource && resource->resource();
|
||||
}
|
||||
|
||||
wl_client* CColorManagementSurface::client() {
|
||||
@@ -339,34 +240,34 @@ bool CColorManagementSurface::needsHdrMetadataUpdate() {
|
||||
return m_needsNewMetadata;
|
||||
}
|
||||
|
||||
CColorManagementFeedbackSurface::CColorManagementFeedbackSurface(SP<CWpColorManagementSurfaceFeedbackV1> resource, SP<CWLSurfaceResource> surface_) :
|
||||
surface(surface_), m_resource(resource) {
|
||||
CColorManagementFeedbackSurface::CColorManagementFeedbackSurface(SP<CXxColorManagementFeedbackSurfaceV4> resource_, SP<CWLSurfaceResource> surface_) :
|
||||
surface(surface_), resource(resource_) {
|
||||
if UNLIKELY (!good())
|
||||
return;
|
||||
|
||||
pClient = m_resource->client();
|
||||
pClient = resource->client();
|
||||
|
||||
m_resource->setDestroy([this](CWpColorManagementSurfaceFeedbackV1* r) {
|
||||
resource->setDestroy([this](CXxColorManagementFeedbackSurfaceV4* r) {
|
||||
LOGM(TRACE, "Destroy xx cm feedback surface {}", (uintptr_t)surface);
|
||||
if (m_currentPreferred.valid())
|
||||
PROTO::colorManagement->destroyResource(m_currentPreferred.get());
|
||||
PROTO::colorManagement->destroyResource(this);
|
||||
});
|
||||
m_resource->setOnDestroy([this](CWpColorManagementSurfaceFeedbackV1* r) {
|
||||
resource->setOnDestroy([this](CXxColorManagementFeedbackSurfaceV4* r) {
|
||||
LOGM(TRACE, "Destroy xx cm feedback surface {}", (uintptr_t)surface);
|
||||
if (m_currentPreferred.valid())
|
||||
PROTO::colorManagement->destroyResource(m_currentPreferred.get());
|
||||
PROTO::colorManagement->destroyResource(this);
|
||||
});
|
||||
|
||||
m_resource->setGetPreferred([this](CWpColorManagementSurfaceFeedbackV1* r, uint32_t id) {
|
||||
resource->setGetPreferred([this](CXxColorManagementFeedbackSurfaceV4* r, uint32_t id) {
|
||||
LOGM(TRACE, "Get preferred for id {}", id);
|
||||
|
||||
if (m_currentPreferred.valid())
|
||||
PROTO::colorManagement->destroyResource(m_currentPreferred.get());
|
||||
|
||||
const auto RESOURCE = PROTO::colorManagement->m_vImageDescriptions.emplace_back(
|
||||
makeShared<CColorManagementImageDescription>(makeShared<CWpImageDescriptionV1>(r->client(), r->version(), id), true));
|
||||
makeShared<CColorManagementImageDescription>(makeShared<CXxImageDescriptionV4>(r->client(), r->version(), id), true));
|
||||
|
||||
if UNLIKELY (!RESOURCE->good()) {
|
||||
r->noMemory();
|
||||
@@ -378,130 +279,44 @@ CColorManagementFeedbackSurface::CColorManagementFeedbackSurface(SP<CWpColorMana
|
||||
m_currentPreferred = RESOURCE;
|
||||
|
||||
m_currentPreferred->settings = g_pCompositor->getPreferredImageDescription();
|
||||
if (!m_currentPreferred->settings.id)
|
||||
m_currentPreferred->settings.id = ++lastImageID;
|
||||
|
||||
RESOURCE->resource()->sendReady(++lastImageID); // FIXME: create correct id
|
||||
});
|
||||
|
||||
m_resource->setGetPreferredParametric([this](CWpColorManagementSurfaceFeedbackV1* r, uint32_t id) {
|
||||
LOGM(TRACE, "Get preferred for id {}", id);
|
||||
|
||||
if (!PROTO::colorManagement->m_debug) {
|
||||
r->error(WP_COLOR_MANAGER_V1_ERROR_UNSUPPORTED_FEATURE, "Parametric descriptions are not supported");
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_currentPreferred.valid())
|
||||
PROTO::colorManagement->destroyResource(m_currentPreferred.get());
|
||||
|
||||
const auto RESOURCE = PROTO::colorManagement->m_vImageDescriptions.emplace_back(
|
||||
makeShared<CColorManagementImageDescription>(makeShared<CWpImageDescriptionV1>(r->client(), r->version(), id), true));
|
||||
|
||||
if UNLIKELY (!RESOURCE->good()) {
|
||||
r->noMemory();
|
||||
PROTO::colorManagement->m_vImageDescriptions.pop_back();
|
||||
return;
|
||||
}
|
||||
|
||||
RESOURCE->self = RESOURCE;
|
||||
m_currentPreferred = RESOURCE;
|
||||
|
||||
m_currentPreferred->settings = g_pCompositor->getPreferredImageDescription();
|
||||
if (!PROTO::colorManagement->m_debug && m_currentPreferred->settings.icc.fd) {
|
||||
LOGM(ERR, "FIXME: parse icc profile");
|
||||
r->error(WP_COLOR_MANAGER_V1_ERROR_UNSUPPORTED_FEATURE, "ICC profiles are not supported");
|
||||
return;
|
||||
}
|
||||
|
||||
RESOURCE->resource()->sendReady(++lastImageID); // FIXME: create correct id
|
||||
RESOURCE->resource()->sendReady(id);
|
||||
});
|
||||
}
|
||||
|
||||
bool CColorManagementFeedbackSurface::good() {
|
||||
return m_resource->resource();
|
||||
return resource->resource();
|
||||
}
|
||||
|
||||
wl_client* CColorManagementFeedbackSurface::client() {
|
||||
return pClient;
|
||||
}
|
||||
|
||||
CColorManagementIccCreator::CColorManagementIccCreator(SP<CWpImageDescriptionCreatorIccV1> resource) : m_resource(resource) {
|
||||
CColorManagementParametricCreator::CColorManagementParametricCreator(SP<CXxImageDescriptionCreatorParamsV4> resource_) : resource(resource_) {
|
||||
if UNLIKELY (!good())
|
||||
return;
|
||||
//
|
||||
pClient = m_resource->client();
|
||||
pClient = resource->client();
|
||||
|
||||
m_resource->setOnDestroy([this](CWpImageDescriptionCreatorIccV1* r) { PROTO::colorManagement->destroyResource(this); });
|
||||
resource->setOnDestroy([this](CXxImageDescriptionCreatorParamsV4* r) { PROTO::colorManagement->destroyResource(this); });
|
||||
|
||||
m_resource->setCreate([this](CWpImageDescriptionCreatorIccV1* r, uint32_t id) {
|
||||
LOGM(TRACE, "Create image description from icc for id {}", id);
|
||||
|
||||
// FIXME actually check completeness
|
||||
if (settings.icc.fd < 0 || !settings.icc.length) {
|
||||
r->error(WP_IMAGE_DESCRIPTION_CREATOR_PARAMS_V1_ERROR_INCOMPLETE_SET, "Missing required settings");
|
||||
return;
|
||||
}
|
||||
|
||||
const auto RESOURCE = PROTO::colorManagement->m_vImageDescriptions.emplace_back(
|
||||
makeShared<CColorManagementImageDescription>(makeShared<CWpImageDescriptionV1>(r->client(), r->version(), id), false));
|
||||
|
||||
if UNLIKELY (!RESOURCE->good()) {
|
||||
r->noMemory();
|
||||
PROTO::colorManagement->m_vImageDescriptions.pop_back();
|
||||
return;
|
||||
}
|
||||
|
||||
LOGM(ERR, "FIXME: Parse icc file {}({},{}) for id {}", settings.icc.fd, settings.icc.offset, settings.icc.length, id);
|
||||
|
||||
// FIXME actually check support
|
||||
if (settings.icc.fd < 0 || !settings.icc.length) {
|
||||
RESOURCE->resource()->sendFailed(WP_IMAGE_DESCRIPTION_V1_CAUSE_UNSUPPORTED, "unsupported");
|
||||
return;
|
||||
}
|
||||
|
||||
RESOURCE->self = RESOURCE;
|
||||
RESOURCE->settings = settings;
|
||||
settings.id = ++lastImageID;
|
||||
RESOURCE->resource()->sendReady(settings.id); // FIXME: create correct id
|
||||
|
||||
PROTO::colorManagement->destroyResource(this);
|
||||
});
|
||||
|
||||
m_resource->setSetIccFile([this](CWpImageDescriptionCreatorIccV1* r, int fd, uint32_t offset, uint32_t length) {
|
||||
settings.icc.fd = fd;
|
||||
settings.icc.offset = offset;
|
||||
settings.icc.length = length;
|
||||
});
|
||||
}
|
||||
|
||||
bool CColorManagementIccCreator::good() {
|
||||
return m_resource->resource();
|
||||
}
|
||||
|
||||
wl_client* CColorManagementIccCreator::client() {
|
||||
return pClient;
|
||||
}
|
||||
|
||||
CColorManagementParametricCreator::CColorManagementParametricCreator(SP<CWpImageDescriptionCreatorParamsV1> resource) : m_resource(resource) {
|
||||
if UNLIKELY (!good())
|
||||
return;
|
||||
//
|
||||
pClient = m_resource->client();
|
||||
|
||||
m_resource->setOnDestroy([this](CWpImageDescriptionCreatorParamsV1* r) { PROTO::colorManagement->destroyResource(this); });
|
||||
|
||||
m_resource->setCreate([this](CWpImageDescriptionCreatorParamsV1* r, uint32_t id) {
|
||||
resource->setCreate([this](CXxImageDescriptionCreatorParamsV4* r, uint32_t id) {
|
||||
LOGM(TRACE, "Create image description from params for id {}", id);
|
||||
|
||||
// FIXME actually check completeness
|
||||
if (!valuesSet) {
|
||||
r->error(WP_IMAGE_DESCRIPTION_CREATOR_PARAMS_V1_ERROR_INCOMPLETE_SET, "Missing required settings");
|
||||
r->error(XX_IMAGE_DESCRIPTION_CREATOR_PARAMS_V4_ERROR_INCOMPLETE_SET, "Missing required settings");
|
||||
return;
|
||||
}
|
||||
|
||||
// FIXME actually check consistency
|
||||
if (!valuesSet) {
|
||||
r->error(XX_IMAGE_DESCRIPTION_CREATOR_PARAMS_V4_ERROR_INCONSISTENT_SET, "Set is not consistent");
|
||||
return;
|
||||
}
|
||||
|
||||
const auto RESOURCE = PROTO::colorManagement->m_vImageDescriptions.emplace_back(
|
||||
makeShared<CColorManagementImageDescription>(makeShared<CWpImageDescriptionV1>(r->client(), r->version(), id), false));
|
||||
makeShared<CColorManagementImageDescription>(makeShared<CXxImageDescriptionV4>(r->client(), r->version(), id)));
|
||||
|
||||
if UNLIKELY (!RESOURCE->good()) {
|
||||
r->noMemory();
|
||||
@@ -511,168 +326,128 @@ CColorManagementParametricCreator::CColorManagementParametricCreator(SP<CWpImage
|
||||
|
||||
// FIXME actually check support
|
||||
if (!valuesSet) {
|
||||
RESOURCE->resource()->sendFailed(WP_IMAGE_DESCRIPTION_V1_CAUSE_UNSUPPORTED, "unsupported");
|
||||
RESOURCE->resource()->sendFailed(XX_IMAGE_DESCRIPTION_V4_CAUSE_UNSUPPORTED, "unsupported");
|
||||
return;
|
||||
}
|
||||
|
||||
RESOURCE->self = RESOURCE;
|
||||
RESOURCE->settings = settings;
|
||||
settings.id = ++lastImageID;
|
||||
RESOURCE->resource()->sendReady(settings.id); // FIXME: create correct id
|
||||
RESOURCE->resource()->sendReady(id);
|
||||
|
||||
PROTO::colorManagement->destroyResource(this);
|
||||
});
|
||||
m_resource->setSetTfNamed([this](CWpImageDescriptionCreatorParamsV1* r, uint32_t tf) {
|
||||
resource->setSetTfNamed([this](CXxImageDescriptionCreatorParamsV4* r, uint32_t tf) {
|
||||
LOGM(TRACE, "Set image description transfer function to {}", tf);
|
||||
if (valuesSet & PC_TF) {
|
||||
r->error(WP_IMAGE_DESCRIPTION_CREATOR_PARAMS_V1_ERROR_ALREADY_SET, "Transfer function already set");
|
||||
r->error(XX_IMAGE_DESCRIPTION_CREATOR_PARAMS_V4_ERROR_ALREADY_SET, "Transfer function already set");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (tf) {
|
||||
case WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_SRGB: break;
|
||||
case WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_ST2084_PQ: break;
|
||||
case WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_EXT_LINEAR: break;
|
||||
case WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_GAMMA22: break;
|
||||
case WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_GAMMA28: break;
|
||||
case WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_HLG: break;
|
||||
default: r->error(WP_IMAGE_DESCRIPTION_CREATOR_PARAMS_V1_ERROR_INVALID_TF, "Unsupported transfer function"); return;
|
||||
case XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_SRGB: break;
|
||||
case XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_ST2084_PQ: break;
|
||||
default: r->error(XX_IMAGE_DESCRIPTION_CREATOR_PARAMS_V4_ERROR_INVALID_TF, "Unsupported transfer function"); return;
|
||||
}
|
||||
|
||||
settings.transferFunction = convertTransferFunction((wpColorManagerV1TransferFunction)tf);
|
||||
settings.transferFunction = (xxColorManagerV4TransferFunction)tf;
|
||||
valuesSet |= PC_TF;
|
||||
});
|
||||
m_resource->setSetTfPower([this](CWpImageDescriptionCreatorParamsV1* r, uint32_t eexp) {
|
||||
resource->setSetTfPower([this](CXxImageDescriptionCreatorParamsV4* r, uint32_t eexp) {
|
||||
LOGM(TRACE, "Set image description tf power to {}", eexp);
|
||||
if (valuesSet & PC_TF_POWER) {
|
||||
r->error(WP_IMAGE_DESCRIPTION_CREATOR_PARAMS_V1_ERROR_ALREADY_SET, "Transfer function power already set");
|
||||
return;
|
||||
}
|
||||
if (!PROTO::colorManagement->m_debug) {
|
||||
r->error(WP_COLOR_MANAGER_V1_ERROR_UNSUPPORTED_FEATURE, "TF power is not supported");
|
||||
r->error(XX_IMAGE_DESCRIPTION_CREATOR_PARAMS_V4_ERROR_ALREADY_SET, "Transfer function power already set");
|
||||
return;
|
||||
}
|
||||
settings.transferFunctionPower = eexp / 10000.0f;
|
||||
if (settings.transferFunctionPower < 1.0 || settings.transferFunctionPower > 10.0) {
|
||||
r->error(WP_IMAGE_DESCRIPTION_CREATOR_PARAMS_V1_ERROR_INVALID_TF, "Power should be between 1.0 and 10.0");
|
||||
return;
|
||||
}
|
||||
valuesSet |= PC_TF_POWER;
|
||||
});
|
||||
m_resource->setSetPrimariesNamed([this](CWpImageDescriptionCreatorParamsV1* r, uint32_t primaries) {
|
||||
resource->setSetPrimariesNamed([this](CXxImageDescriptionCreatorParamsV4* r, uint32_t primaries) {
|
||||
LOGM(TRACE, "Set image description primaries by name {}", primaries);
|
||||
if (valuesSet & PC_PRIMARIES) {
|
||||
r->error(WP_IMAGE_DESCRIPTION_CREATOR_PARAMS_V1_ERROR_ALREADY_SET, "Primaries already set");
|
||||
r->error(XX_IMAGE_DESCRIPTION_CREATOR_PARAMS_V4_ERROR_ALREADY_SET, "Primaries already set");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (primaries) {
|
||||
case WP_COLOR_MANAGER_V1_PRIMARIES_SRGB:
|
||||
case WP_COLOR_MANAGER_V1_PRIMARIES_BT2020:
|
||||
case WP_COLOR_MANAGER_V1_PRIMARIES_PAL_M:
|
||||
case WP_COLOR_MANAGER_V1_PRIMARIES_PAL:
|
||||
case WP_COLOR_MANAGER_V1_PRIMARIES_NTSC:
|
||||
case WP_COLOR_MANAGER_V1_PRIMARIES_GENERIC_FILM:
|
||||
case WP_COLOR_MANAGER_V1_PRIMARIES_DCI_P3:
|
||||
case WP_COLOR_MANAGER_V1_PRIMARIES_DISPLAY_P3:
|
||||
case WP_COLOR_MANAGER_V1_PRIMARIES_ADOBE_RGB: break;
|
||||
default:
|
||||
if (!PROTO::colorManagement->m_debug) {
|
||||
r->error(WP_IMAGE_DESCRIPTION_CREATOR_PARAMS_V1_ERROR_INVALID_PRIMARIES_NAMED, "Unsupported primaries");
|
||||
return;
|
||||
}
|
||||
case XX_COLOR_MANAGER_V4_PRIMARIES_SRGB:
|
||||
settings.primariesNameSet = true;
|
||||
settings.primariesNamed = XX_COLOR_MANAGER_V4_PRIMARIES_SRGB;
|
||||
settings.primaries = NColorPrimaries::BT709;
|
||||
valuesSet |= PC_PRIMARIES;
|
||||
break;
|
||||
case XX_COLOR_MANAGER_V4_PRIMARIES_BT2020:
|
||||
settings.primariesNameSet = true;
|
||||
settings.primariesNamed = XX_COLOR_MANAGER_V4_PRIMARIES_BT2020;
|
||||
settings.primaries = NColorPrimaries::BT2020;
|
||||
valuesSet |= PC_PRIMARIES;
|
||||
break;
|
||||
default: r->error(XX_IMAGE_DESCRIPTION_CREATOR_PARAMS_V4_ERROR_INVALID_PRIMARIES, "Unsupported primaries");
|
||||
}
|
||||
|
||||
settings.primariesNameSet = true;
|
||||
settings.primariesNamed = convertPrimaries((wpColorManagerV1Primaries)primaries);
|
||||
settings.primaries = getPrimaries(settings.primariesNamed);
|
||||
valuesSet |= PC_PRIMARIES;
|
||||
});
|
||||
m_resource->setSetPrimaries(
|
||||
[this](CWpImageDescriptionCreatorParamsV1* r, int32_t r_x, int32_t r_y, int32_t g_x, int32_t g_y, int32_t b_x, int32_t b_y, int32_t w_x, int32_t w_y) {
|
||||
resource->setSetPrimaries(
|
||||
[this](CXxImageDescriptionCreatorParamsV4* r, int32_t r_x, int32_t r_y, int32_t g_x, int32_t g_y, int32_t b_x, int32_t b_y, int32_t w_x, int32_t w_y) {
|
||||
LOGM(TRACE, "Set image description primaries by values r:{},{} g:{},{} b:{},{} w:{},{}", r_x, r_y, g_x, g_y, b_x, b_y, w_x, w_y);
|
||||
if (valuesSet & PC_PRIMARIES) {
|
||||
r->error(WP_IMAGE_DESCRIPTION_CREATOR_PARAMS_V1_ERROR_ALREADY_SET, "Primaries already set");
|
||||
return;
|
||||
}
|
||||
if (!PROTO::colorManagement->m_debug) {
|
||||
r->error(WP_COLOR_MANAGER_V1_ERROR_UNSUPPORTED_FEATURE, "Custom primaries aren't supported");
|
||||
r->error(XX_IMAGE_DESCRIPTION_CREATOR_PARAMS_V4_ERROR_ALREADY_SET, "Primaries already set");
|
||||
return;
|
||||
}
|
||||
settings.primariesNameSet = false;
|
||||
settings.primaries = SPCPRimaries{.red = {.x = r_x / 1000000.0f, .y = r_y / 1000000.0f},
|
||||
.green = {.x = g_x / 1000000.0f, .y = g_y / 1000000.0f},
|
||||
.blue = {.x = b_x / 1000000.0f, .y = b_y / 1000000.0f},
|
||||
.white = {.x = w_x / 1000000.0f, .y = w_y / 1000000.0f}};
|
||||
settings.primaries =
|
||||
SImageDescription::SPCPRimaries{.red = {.x = r_x, .y = r_y}, .green = {.x = g_x, .y = g_y}, .blue = {.x = b_x, .y = b_y}, .white = {.x = w_x, .y = w_y}};
|
||||
valuesSet |= PC_PRIMARIES;
|
||||
});
|
||||
m_resource->setSetLuminances([this](CWpImageDescriptionCreatorParamsV1* r, uint32_t min_lum, uint32_t max_lum, uint32_t reference_lum) {
|
||||
resource->setSetLuminances([this](CXxImageDescriptionCreatorParamsV4* r, uint32_t min_lum, uint32_t max_lum, uint32_t reference_lum) {
|
||||
auto min = min_lum / 10000.0f;
|
||||
LOGM(TRACE, "Set image description luminances to {} - {} ({})", min, max_lum, reference_lum);
|
||||
if (valuesSet & PC_LUMINANCES) {
|
||||
r->error(WP_IMAGE_DESCRIPTION_CREATOR_PARAMS_V1_ERROR_ALREADY_SET, "Luminances already set");
|
||||
r->error(XX_IMAGE_DESCRIPTION_CREATOR_PARAMS_V4_ERROR_ALREADY_SET, "Luminances already set");
|
||||
return;
|
||||
}
|
||||
if (max_lum < reference_lum || reference_lum <= min) {
|
||||
r->error(WP_IMAGE_DESCRIPTION_CREATOR_PARAMS_V1_ERROR_INVALID_LUMINANCE, "Invalid luminances");
|
||||
r->error(XX_IMAGE_DESCRIPTION_CREATOR_PARAMS_V4_ERROR_INVALID_LUMINANCE, "Invalid luminances");
|
||||
return;
|
||||
}
|
||||
settings.luminances = SImageDescription::SPCLuminances{.min = min, .max = max_lum, .reference = reference_lum};
|
||||
valuesSet |= PC_LUMINANCES;
|
||||
});
|
||||
m_resource->setSetMasteringDisplayPrimaries(
|
||||
[this](CWpImageDescriptionCreatorParamsV1* r, int32_t r_x, int32_t r_y, int32_t g_x, int32_t g_y, int32_t b_x, int32_t b_y, int32_t w_x, int32_t w_y) {
|
||||
resource->setSetMasteringDisplayPrimaries(
|
||||
[this](CXxImageDescriptionCreatorParamsV4* r, int32_t r_x, int32_t r_y, int32_t g_x, int32_t g_y, int32_t b_x, int32_t b_y, int32_t w_x, int32_t w_y) {
|
||||
LOGM(TRACE, "Set image description mastering primaries by values r:{},{} g:{},{} b:{},{} w:{},{}", r_x, r_y, g_x, g_y, b_x, b_y, w_x, w_y);
|
||||
if (valuesSet & PC_MASTERING_PRIMARIES) {
|
||||
r->error(WP_IMAGE_DESCRIPTION_CREATOR_PARAMS_V1_ERROR_ALREADY_SET, "Mastering primaries already set");
|
||||
return;
|
||||
}
|
||||
if (!PROTO::colorManagement->m_debug) {
|
||||
r->error(WP_COLOR_MANAGER_V1_ERROR_UNSUPPORTED_FEATURE, "Mastering primaries are not supported");
|
||||
return;
|
||||
}
|
||||
settings.masteringPrimaries = SPCPRimaries{.red = {.x = r_x / 1000000.0f, .y = r_y / 1000000.0f},
|
||||
.green = {.x = g_x / 1000000.0f, .y = g_y / 1000000.0f},
|
||||
.blue = {.x = b_x / 1000000.0f, .y = b_y / 1000000.0f},
|
||||
.white = {.x = w_x / 1000000.0f, .y = w_y / 1000000.0f}};
|
||||
// if (valuesSet & PC_MASTERING_PRIMARIES) {
|
||||
// r->error(XX_IMAGE_DESCRIPTION_CREATOR_PARAMS_V4_ERROR_ALREADY_SET, "Mastering primaries already set");
|
||||
// return;
|
||||
// }
|
||||
settings.masteringPrimaries =
|
||||
SImageDescription::SPCPRimaries{.red = {.x = r_x, .y = r_y}, .green = {.x = g_x, .y = g_y}, .blue = {.x = b_x, .y = b_y}, .white = {.x = w_x, .y = w_y}};
|
||||
valuesSet |= PC_MASTERING_PRIMARIES;
|
||||
|
||||
// FIXME:
|
||||
// If a compositor additionally supports target color volume exceeding the primary color volume, it must advertise wp_color_manager_v1.feature.extended_target_volume.
|
||||
// If a client uses target color volume exceeding the primary color volume and the compositor does not support it, the result is implementation defined.
|
||||
// Compositors are recommended to detect this case and fail the image description gracefully, but it may as well result in color artifacts.
|
||||
});
|
||||
m_resource->setSetMasteringLuminance([this](CWpImageDescriptionCreatorParamsV1* r, uint32_t min_lum, uint32_t max_lum) {
|
||||
resource->setSetMasteringLuminance([this](CXxImageDescriptionCreatorParamsV4* r, uint32_t min_lum, uint32_t max_lum) {
|
||||
auto min = min_lum / 10000.0f;
|
||||
LOGM(TRACE, "Set image description mastering luminances to {} - {}", min, max_lum);
|
||||
// if (valuesSet & PC_MASTERING_LUMINANCES) {
|
||||
// r->error(WP_IMAGE_DESCRIPTION_CREATOR_PARAMS_V1_ERROR_ALREADY_SET, "Mastering luminances already set");
|
||||
// r->error(XX_IMAGE_DESCRIPTION_CREATOR_PARAMS_V4_ERROR_ALREADY_SET, "Mastering luminances already set");
|
||||
// return;
|
||||
// }
|
||||
if (min > 0 && max_lum > 0 && max_lum <= min) {
|
||||
r->error(WP_IMAGE_DESCRIPTION_CREATOR_PARAMS_V1_ERROR_INVALID_LUMINANCE, "Invalid luminances");
|
||||
return;
|
||||
}
|
||||
if (!PROTO::colorManagement->m_debug) {
|
||||
r->error(WP_COLOR_MANAGER_V1_ERROR_UNSUPPORTED_FEATURE, "Mastering luminances are not supported");
|
||||
r->error(XX_IMAGE_DESCRIPTION_CREATOR_PARAMS_V4_ERROR_INVALID_LUMINANCE, "Invalid luminances");
|
||||
return;
|
||||
}
|
||||
settings.masteringLuminances = SImageDescription::SPCMasteringLuminances{.min = min, .max = max_lum};
|
||||
valuesSet |= PC_MASTERING_LUMINANCES;
|
||||
});
|
||||
m_resource->setSetMaxCll([this](CWpImageDescriptionCreatorParamsV1* r, uint32_t max_cll) {
|
||||
resource->setSetMaxCll([this](CXxImageDescriptionCreatorParamsV4* r, uint32_t max_cll) {
|
||||
LOGM(TRACE, "Set image description max content light level to {}", max_cll);
|
||||
// if (valuesSet & PC_CLL) {
|
||||
// r->error(WP_IMAGE_DESCRIPTION_CREATOR_PARAMS_V1_ERROR_ALREADY_SET, "Max CLL already set");
|
||||
// r->error(XX_IMAGE_DESCRIPTION_CREATOR_PARAMS_V4_ERROR_ALREADY_SET, "Max CLL already set");
|
||||
// return;
|
||||
// }
|
||||
settings.maxCLL = max_cll;
|
||||
valuesSet |= PC_CLL;
|
||||
});
|
||||
m_resource->setSetMaxFall([this](CWpImageDescriptionCreatorParamsV1* r, uint32_t max_fall) {
|
||||
resource->setSetMaxFall([this](CXxImageDescriptionCreatorParamsV4* r, uint32_t max_fall) {
|
||||
LOGM(TRACE, "Set image description max frame-average light level to {}", max_fall);
|
||||
// if (valuesSet & PC_FALL) {
|
||||
// r->error(WP_IMAGE_DESCRIPTION_CREATOR_PARAMS_V1_ERROR_ALREADY_SET, "Max FALL already set");
|
||||
// r->error(XX_IMAGE_DESCRIPTION_CREATOR_PARAMS_V4_ERROR_ALREADY_SET, "Max FALL already set");
|
||||
// return;
|
||||
// }
|
||||
settings.maxFALL = max_fall;
|
||||
@@ -681,31 +456,31 @@ CColorManagementParametricCreator::CColorManagementParametricCreator(SP<CWpImage
|
||||
}
|
||||
|
||||
bool CColorManagementParametricCreator::good() {
|
||||
return m_resource->resource();
|
||||
return resource->resource();
|
||||
}
|
||||
|
||||
wl_client* CColorManagementParametricCreator::client() {
|
||||
return pClient;
|
||||
}
|
||||
|
||||
CColorManagementImageDescription::CColorManagementImageDescription(SP<CWpImageDescriptionV1> resource, bool allowGetInformation) :
|
||||
m_resource(resource), m_allowGetInformation(allowGetInformation) {
|
||||
CColorManagementImageDescription::CColorManagementImageDescription(SP<CXxImageDescriptionV4> resource_, bool allowGetInformation) :
|
||||
m_resource(resource_), m_allowGetInformation(allowGetInformation) {
|
||||
if UNLIKELY (!good())
|
||||
return;
|
||||
|
||||
pClient = m_resource->client();
|
||||
|
||||
m_resource->setDestroy([this](CWpImageDescriptionV1* r) { PROTO::colorManagement->destroyResource(this); });
|
||||
m_resource->setOnDestroy([this](CWpImageDescriptionV1* r) { PROTO::colorManagement->destroyResource(this); });
|
||||
m_resource->setDestroy([this](CXxImageDescriptionV4* r) { PROTO::colorManagement->destroyResource(this); });
|
||||
m_resource->setOnDestroy([this](CXxImageDescriptionV4* r) { PROTO::colorManagement->destroyResource(this); });
|
||||
|
||||
m_resource->setGetInformation([this](CWpImageDescriptionV1* r, uint32_t id) {
|
||||
m_resource->setGetInformation([this](CXxImageDescriptionV4* r, uint32_t id) {
|
||||
LOGM(TRACE, "Get image information for image={}, id={}", (uintptr_t)r, id);
|
||||
if (!m_allowGetInformation) {
|
||||
r->error(WP_IMAGE_DESCRIPTION_V1_ERROR_NO_INFORMATION, "Image descriptions doesn't allow get_information request");
|
||||
r->error(XX_IMAGE_DESCRIPTION_V4_ERROR_NO_INFORMATION, "Image descriptions doesn't allow get_information request");
|
||||
return;
|
||||
}
|
||||
|
||||
auto RESOURCE = makeShared<CColorManagementImageDescriptionInfo>(makeShared<CWpImageDescriptionInfoV1>(r->client(), r->version(), id), settings);
|
||||
auto RESOURCE = makeShared<CColorManagementImageDescriptionInfo>(makeShared<CXxImageDescriptionInfoV4>(r->client(), r->version(), id), settings);
|
||||
|
||||
if UNLIKELY (!RESOURCE->good())
|
||||
r->noMemory();
|
||||
@@ -723,12 +498,12 @@ wl_client* CColorManagementImageDescription::client() {
|
||||
return pClient;
|
||||
}
|
||||
|
||||
SP<CWpImageDescriptionV1> CColorManagementImageDescription::resource() {
|
||||
SP<CXxImageDescriptionV4> CColorManagementImageDescription::resource() {
|
||||
return m_resource;
|
||||
}
|
||||
|
||||
CColorManagementImageDescriptionInfo::CColorManagementImageDescriptionInfo(SP<CWpImageDescriptionInfoV1> resource, const SImageDescription& settings_) :
|
||||
m_resource(resource), settings(settings_) {
|
||||
CColorManagementImageDescriptionInfo::CColorManagementImageDescriptionInfo(SP<CXxImageDescriptionInfoV4> resource_, const SImageDescription& settings_) :
|
||||
m_resource(resource_), settings(settings_) {
|
||||
if UNLIKELY (!good())
|
||||
return;
|
||||
|
||||
@@ -736,8 +511,8 @@ CColorManagementImageDescriptionInfo::CColorManagementImageDescriptionInfo(SP<CW
|
||||
|
||||
const auto toProto = [](float value) { return int32_t(std::round(value * 10000)); };
|
||||
|
||||
if (settings.icc.fd >= 0)
|
||||
m_resource->sendIccFile(settings.icc.fd, settings.icc.length);
|
||||
if (settings.iccFd >= 0)
|
||||
m_resource->sendIccFile(settings.iccFd, settings.iccSize);
|
||||
|
||||
// send preferred client paramateres
|
||||
m_resource->sendPrimaries(toProto(settings.primaries.red.x), toProto(settings.primaries.red.y), toProto(settings.primaries.green.x), toProto(settings.primaries.green.y),
|
||||
@@ -767,13 +542,12 @@ wl_client* CColorManagementImageDescriptionInfo::client() {
|
||||
return pClient;
|
||||
}
|
||||
|
||||
CColorManagementProtocol::CColorManagementProtocol(const wl_interface* iface, const int& ver, const std::string& name, bool debug) :
|
||||
IWaylandProtocol(iface, ver, name), m_debug(debug) {
|
||||
CColorManagementProtocol::CColorManagementProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) {
|
||||
;
|
||||
}
|
||||
|
||||
void CColorManagementProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) {
|
||||
const auto RESOURCE = m_vManagers.emplace_back(makeShared<CColorManager>(makeShared<CWpColorManagerV1>(client, ver, id)));
|
||||
const auto RESOURCE = m_vManagers.emplace_back(makeShared<CColorManager>(makeShared<CXxColorManagerV4>(client, ver, id)));
|
||||
|
||||
if UNLIKELY (!RESOURCE->good()) {
|
||||
wl_client_post_no_memory(client);
|
||||
@@ -781,19 +555,12 @@ void CColorManagementProtocol::bindManager(wl_client* client, void* data, uint32
|
||||
return;
|
||||
}
|
||||
|
||||
LOGM(TRACE, "New WP_color_manager at {:x}", (uintptr_t)RESOURCE.get());
|
||||
LOGM(TRACE, "New xx_color_manager at {:x}", (uintptr_t)RESOURCE.get());
|
||||
}
|
||||
|
||||
void CColorManagementProtocol::onImagePreferredChanged(uint32_t preferredId) {
|
||||
void CColorManagementProtocol::onImagePreferredChanged() {
|
||||
for (auto const& feedback : m_vFeedbackSurfaces) {
|
||||
feedback->m_resource->sendPreferredChanged(preferredId);
|
||||
}
|
||||
}
|
||||
|
||||
void CColorManagementProtocol::onMonitorImageDescriptionChanged(WP<CMonitor> monitor) {
|
||||
for (auto const& output : m_vOutputs) {
|
||||
if (output->m_monitor == monitor)
|
||||
output->m_resource->sendImageDescriptionChanged();
|
||||
feedback->resource->sendPreferredChanged();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -813,10 +580,6 @@ void CColorManagementProtocol::destroyResource(CColorManagementFeedbackSurface*
|
||||
std::erase_if(m_vFeedbackSurfaces, [&](const auto& other) { return other.get() == resource; });
|
||||
}
|
||||
|
||||
void CColorManagementProtocol::destroyResource(CColorManagementIccCreator* resource) {
|
||||
std::erase_if(m_vIccCreators, [&](const auto& other) { return other.get() == resource; });
|
||||
}
|
||||
|
||||
void CColorManagementProtocol::destroyResource(CColorManagementParametricCreator* resource) {
|
||||
std::erase_if(m_vParametricCreators, [&](const auto& other) { return other.get() == resource; });
|
||||
}
|
||||
|
@@ -4,9 +4,8 @@
|
||||
#include <vector>
|
||||
#include <cstdint>
|
||||
#include "WaylandProtocol.hpp"
|
||||
#include "../helpers/Monitor.hpp"
|
||||
#include "core/Compositor.hpp"
|
||||
#include "color-management-v1.hpp"
|
||||
#include "protocols/core/Compositor.hpp"
|
||||
#include "xx-color-management-v4.hpp"
|
||||
#include "types/ColorManagement.hpp"
|
||||
|
||||
class CColorManager;
|
||||
@@ -16,17 +15,17 @@ class CColorManagementProtocol;
|
||||
|
||||
class CColorManager {
|
||||
public:
|
||||
CColorManager(SP<CWpColorManagerV1> resource);
|
||||
CColorManager(SP<CXxColorManagerV4> resource_);
|
||||
|
||||
bool good();
|
||||
|
||||
private:
|
||||
SP<CWpColorManagerV1> m_resource;
|
||||
SP<CXxColorManagerV4> resource;
|
||||
};
|
||||
|
||||
class CColorManagementOutput {
|
||||
public:
|
||||
CColorManagementOutput(SP<CWpColorManagementOutputV1> resource, WP<CMonitor> monitor);
|
||||
CColorManagementOutput(SP<CXxColorManagementOutputV4> resource_);
|
||||
|
||||
bool good();
|
||||
wl_client* client();
|
||||
@@ -35,9 +34,8 @@ class CColorManagementOutput {
|
||||
WP<CColorManagementImageDescription> imageDescription;
|
||||
|
||||
private:
|
||||
SP<CWpColorManagementOutputV1> m_resource;
|
||||
SP<CXxColorManagementOutputV4> resource;
|
||||
wl_client* pClient = nullptr;
|
||||
WP<CMonitor> m_monitor;
|
||||
|
||||
friend class CColorManagementProtocol;
|
||||
friend class CColorManagementImageDescription;
|
||||
@@ -46,36 +44,35 @@ class CColorManagementOutput {
|
||||
class CColorManagementSurface {
|
||||
public:
|
||||
CColorManagementSurface(SP<CWLSurfaceResource> surface_); // temporary interface for frog CM
|
||||
CColorManagementSurface(SP<CWpColorManagementSurfaceV1> resource, SP<CWLSurfaceResource> surface_);
|
||||
CColorManagementSurface(SP<CXxColorManagementSurfaceV4> resource_, SP<CWLSurfaceResource> surface_);
|
||||
|
||||
bool good();
|
||||
wl_client* client();
|
||||
bool good();
|
||||
wl_client* client();
|
||||
|
||||
WP<CColorManagementSurface> self;
|
||||
WP<CWLSurfaceResource> surface;
|
||||
WP<CColorManagementSurface> self;
|
||||
WP<CWLSurfaceResource> surface;
|
||||
|
||||
const NColorManagement::SImageDescription& imageDescription();
|
||||
bool hasImageDescription();
|
||||
void setHasImageDescription(bool has);
|
||||
const hdr_output_metadata& hdrMetadata();
|
||||
void setHDRMetadata(const hdr_output_metadata& metadata);
|
||||
bool needsHdrMetadataUpdate();
|
||||
const SImageDescription& imageDescription();
|
||||
bool hasImageDescription();
|
||||
void setHasImageDescription(bool has);
|
||||
const hdr_output_metadata& hdrMetadata();
|
||||
void setHDRMetadata(const hdr_output_metadata& metadata);
|
||||
bool needsHdrMetadataUpdate();
|
||||
|
||||
private:
|
||||
SP<CWpColorManagementSurfaceV1> m_resource;
|
||||
wl_client* pClient = nullptr;
|
||||
NColorManagement::SImageDescription m_imageDescription;
|
||||
bool m_hasImageDescription = false;
|
||||
bool m_needsNewMetadata = false;
|
||||
hdr_output_metadata m_hdrMetadata;
|
||||
SP<CXxColorManagementSurfaceV4> resource;
|
||||
wl_client* pClient = nullptr;
|
||||
SImageDescription m_imageDescription;
|
||||
bool m_hasImageDescription = false;
|
||||
bool m_needsNewMetadata = false;
|
||||
hdr_output_metadata m_hdrMetadata;
|
||||
|
||||
friend class CXXColorManagementSurface;
|
||||
friend class CFrogColorManagementSurface;
|
||||
};
|
||||
|
||||
class CColorManagementFeedbackSurface {
|
||||
public:
|
||||
CColorManagementFeedbackSurface(SP<CWpColorManagementSurfaceFeedbackV1> resource, SP<CWLSurfaceResource> surface_);
|
||||
CColorManagementFeedbackSurface(SP<CXxColorManagementFeedbackSurfaceV4> resource_, SP<CWLSurfaceResource> surface_);
|
||||
|
||||
bool good();
|
||||
wl_client* client();
|
||||
@@ -84,7 +81,7 @@ class CColorManagementFeedbackSurface {
|
||||
WP<CWLSurfaceResource> surface;
|
||||
|
||||
private:
|
||||
SP<CWpColorManagementSurfaceFeedbackV1> m_resource;
|
||||
SP<CXxColorManagementFeedbackSurfaceV4> resource;
|
||||
wl_client* pClient = nullptr;
|
||||
|
||||
WP<CColorManagementImageDescription> m_currentPreferred;
|
||||
@@ -92,32 +89,16 @@ class CColorManagementFeedbackSurface {
|
||||
friend class CColorManagementProtocol;
|
||||
};
|
||||
|
||||
class CColorManagementIccCreator {
|
||||
public:
|
||||
CColorManagementIccCreator(SP<CWpImageDescriptionCreatorIccV1> resource);
|
||||
|
||||
bool good();
|
||||
wl_client* client();
|
||||
|
||||
WP<CColorManagementIccCreator> self;
|
||||
|
||||
NColorManagement::SImageDescription settings;
|
||||
|
||||
private:
|
||||
SP<CWpImageDescriptionCreatorIccV1> m_resource;
|
||||
wl_client* pClient = nullptr;
|
||||
};
|
||||
|
||||
class CColorManagementParametricCreator {
|
||||
public:
|
||||
CColorManagementParametricCreator(SP<CWpImageDescriptionCreatorParamsV1> resource);
|
||||
CColorManagementParametricCreator(SP<CXxImageDescriptionCreatorParamsV4> resource_);
|
||||
|
||||
bool good();
|
||||
wl_client* client();
|
||||
|
||||
WP<CColorManagementParametricCreator> self;
|
||||
|
||||
NColorManagement::SImageDescription settings;
|
||||
SImageDescription settings;
|
||||
|
||||
private:
|
||||
enum eValuesSet : uint32_t { // NOLINT
|
||||
@@ -131,25 +112,25 @@ class CColorManagementParametricCreator {
|
||||
PC_FALL = (1 << 7),
|
||||
};
|
||||
|
||||
SP<CWpImageDescriptionCreatorParamsV1> m_resource;
|
||||
SP<CXxImageDescriptionCreatorParamsV4> resource;
|
||||
wl_client* pClient = nullptr;
|
||||
uint32_t valuesSet = 0; // enum eValuesSet
|
||||
};
|
||||
|
||||
class CColorManagementImageDescription {
|
||||
public:
|
||||
CColorManagementImageDescription(SP<CWpImageDescriptionV1> resource, bool allowGetInformation);
|
||||
CColorManagementImageDescription(SP<CXxImageDescriptionV4> resource_, bool allowGetInformation = false);
|
||||
|
||||
bool good();
|
||||
wl_client* client();
|
||||
SP<CWpImageDescriptionV1> resource();
|
||||
SP<CXxImageDescriptionV4> resource();
|
||||
|
||||
WP<CColorManagementImageDescription> self;
|
||||
|
||||
NColorManagement::SImageDescription settings;
|
||||
SImageDescription settings;
|
||||
|
||||
private:
|
||||
SP<CWpImageDescriptionV1> m_resource;
|
||||
SP<CXxImageDescriptionV4> m_resource;
|
||||
wl_client* pClient = nullptr;
|
||||
bool m_allowGetInformation = false;
|
||||
|
||||
@@ -158,32 +139,30 @@ class CColorManagementImageDescription {
|
||||
|
||||
class CColorManagementImageDescriptionInfo {
|
||||
public:
|
||||
CColorManagementImageDescriptionInfo(SP<CWpImageDescriptionInfoV1> resource, const NColorManagement::SImageDescription& settings_);
|
||||
CColorManagementImageDescriptionInfo(SP<CXxImageDescriptionInfoV4> resource_, const SImageDescription& settings_);
|
||||
|
||||
bool good();
|
||||
wl_client* client();
|
||||
|
||||
private:
|
||||
SP<CWpImageDescriptionInfoV1> m_resource;
|
||||
wl_client* pClient = nullptr;
|
||||
NColorManagement::SImageDescription settings;
|
||||
SP<CXxImageDescriptionInfoV4> m_resource;
|
||||
wl_client* pClient = nullptr;
|
||||
SImageDescription settings;
|
||||
};
|
||||
|
||||
class CColorManagementProtocol : public IWaylandProtocol {
|
||||
public:
|
||||
CColorManagementProtocol(const wl_interface* iface, const int& ver, const std::string& name, bool debug = false);
|
||||
CColorManagementProtocol(const wl_interface* iface, const int& ver, const std::string& name);
|
||||
|
||||
virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id);
|
||||
|
||||
void onImagePreferredChanged(uint32_t preferredId);
|
||||
void onMonitorImageDescriptionChanged(WP<CMonitor> monitor);
|
||||
void onImagePreferredChanged();
|
||||
|
||||
private:
|
||||
void destroyResource(CColorManager* resource);
|
||||
void destroyResource(CColorManagementOutput* resource);
|
||||
void destroyResource(CColorManagementSurface* resource);
|
||||
void destroyResource(CColorManagementFeedbackSurface* resource);
|
||||
void destroyResource(CColorManagementIccCreator* resource);
|
||||
void destroyResource(CColorManagementParametricCreator* resource);
|
||||
void destroyResource(CColorManagementImageDescription* resource);
|
||||
|
||||
@@ -191,20 +170,16 @@ class CColorManagementProtocol : public IWaylandProtocol {
|
||||
std::vector<SP<CColorManagementOutput>> m_vOutputs;
|
||||
std::vector<SP<CColorManagementSurface>> m_vSurfaces;
|
||||
std::vector<SP<CColorManagementFeedbackSurface>> m_vFeedbackSurfaces;
|
||||
std::vector<SP<CColorManagementIccCreator>> m_vIccCreators;
|
||||
std::vector<SP<CColorManagementParametricCreator>> m_vParametricCreators;
|
||||
std::vector<SP<CColorManagementImageDescription>> m_vImageDescriptions;
|
||||
bool m_debug = false;
|
||||
|
||||
friend class CColorManager;
|
||||
friend class CColorManagementOutput;
|
||||
friend class CColorManagementSurface;
|
||||
friend class CColorManagementFeedbackSurface;
|
||||
friend class CColorManagementIccCreator;
|
||||
friend class CColorManagementParametricCreator;
|
||||
friend class CColorManagementImageDescription;
|
||||
|
||||
friend class CXXColorManagementSurface;
|
||||
friend class CFrogColorManagementSurface;
|
||||
};
|
||||
|
||||
|
@@ -1,95 +0,0 @@
|
||||
#include "ContentType.hpp"
|
||||
#include "content-type-v1.hpp"
|
||||
#include "protocols/types/ContentType.hpp"
|
||||
|
||||
CContentTypeManager::CContentTypeManager(SP<CWpContentTypeManagerV1> resource) : m_resource(resource) {
|
||||
if UNLIKELY (!good())
|
||||
return;
|
||||
|
||||
resource->setDestroy([](CWpContentTypeManagerV1* r) {});
|
||||
resource->setOnDestroy([this](CWpContentTypeManagerV1* r) { PROTO::contentType->destroyResource(this); });
|
||||
|
||||
resource->setGetSurfaceContentType([](CWpContentTypeManagerV1* r, uint32_t id, wl_resource* surface) {
|
||||
LOGM(TRACE, "Get surface for id={}, surface={}", id, (uintptr_t)surface);
|
||||
auto SURF = CWLSurfaceResource::fromResource(surface);
|
||||
|
||||
if (!SURF) {
|
||||
LOGM(ERR, "No surface for resource {}", (uintptr_t)surface);
|
||||
r->error(-1, "Invalid surface (2)");
|
||||
return;
|
||||
}
|
||||
|
||||
if (SURF->colorManagement) {
|
||||
r->error(WP_CONTENT_TYPE_MANAGER_V1_ERROR_ALREADY_CONSTRUCTED, "CT manager already exists");
|
||||
return;
|
||||
}
|
||||
|
||||
const auto RESOURCE = PROTO::contentType->m_vContentTypes.emplace_back(makeShared<CContentType>(makeShared<CWpContentTypeV1>(r->client(), r->version(), id)));
|
||||
if UNLIKELY (!RESOURCE->good()) {
|
||||
r->noMemory();
|
||||
PROTO::contentType->m_vContentTypes.pop_back();
|
||||
return;
|
||||
}
|
||||
|
||||
RESOURCE->self = RESOURCE;
|
||||
|
||||
SURF->contentType = RESOURCE;
|
||||
});
|
||||
}
|
||||
|
||||
bool CContentTypeManager::good() {
|
||||
return m_resource->resource();
|
||||
}
|
||||
|
||||
CContentType::CContentType(WP<CWLSurfaceResource> surface) {
|
||||
destroy = surface->events.destroy.registerListener([this](std::any d) { PROTO::contentType->destroyResource(this); });
|
||||
}
|
||||
|
||||
CContentType::CContentType(SP<CWpContentTypeV1> resource) : m_resource(resource) {
|
||||
if UNLIKELY (!good())
|
||||
return;
|
||||
|
||||
m_pClient = resource->client();
|
||||
|
||||
resource->setDestroy([this](CWpContentTypeV1* r) { PROTO::contentType->destroyResource(this); });
|
||||
resource->setOnDestroy([this](CWpContentTypeV1* r) { PROTO::contentType->destroyResource(this); });
|
||||
|
||||
resource->setSetContentType([this](CWpContentTypeV1* r, wpContentTypeV1Type type) { value = NContentType::fromWP(type); });
|
||||
}
|
||||
|
||||
bool CContentType::good() {
|
||||
return m_resource && m_resource->resource();
|
||||
}
|
||||
|
||||
wl_client* CContentType::client() {
|
||||
return m_pClient;
|
||||
}
|
||||
|
||||
CContentTypeProtocol::CContentTypeProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) {
|
||||
;
|
||||
}
|
||||
|
||||
void CContentTypeProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) {
|
||||
const auto RESOURCE = m_vManagers.emplace_back(makeShared<CContentTypeManager>(makeShared<CWpContentTypeManagerV1>(client, ver, id)));
|
||||
|
||||
if UNLIKELY (!RESOURCE->good()) {
|
||||
wl_client_post_no_memory(client);
|
||||
m_vManagers.pop_back();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
SP<CContentType> CContentTypeProtocol::getContentType(WP<CWLSurfaceResource> surface) {
|
||||
if (surface->contentType.valid())
|
||||
return surface->contentType.lock();
|
||||
|
||||
return m_vContentTypes.emplace_back(makeShared<CContentType>(surface));
|
||||
}
|
||||
|
||||
void CContentTypeProtocol::destroyResource(CContentTypeManager* resource) {
|
||||
std::erase_if(m_vManagers, [&](const auto& other) { return other.get() == resource; });
|
||||
}
|
||||
|
||||
void CContentTypeProtocol::destroyResource(CContentType* resource) {
|
||||
std::erase_if(m_vContentTypes, [&](const auto& other) { return other.get() == resource; });
|
||||
}
|
@@ -1,59 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "WaylandProtocol.hpp"
|
||||
#include "core/Compositor.hpp"
|
||||
#include "content-type-v1.hpp"
|
||||
#include "types/ContentType.hpp"
|
||||
|
||||
class CContentTypeManager {
|
||||
public:
|
||||
CContentTypeManager(SP<CWpContentTypeManagerV1> resource);
|
||||
|
||||
bool good();
|
||||
|
||||
private:
|
||||
SP<CWpContentTypeManagerV1> m_resource;
|
||||
};
|
||||
|
||||
class CContentType {
|
||||
public:
|
||||
CContentType(SP<CWpContentTypeV1> resource);
|
||||
CContentType(WP<CWLSurfaceResource> surface);
|
||||
|
||||
bool good();
|
||||
wl_client* client();
|
||||
NContentType::eContentType value = NContentType::CONTENT_TYPE_NONE;
|
||||
|
||||
WP<CContentType> self;
|
||||
|
||||
private:
|
||||
SP<CWpContentTypeV1> m_resource;
|
||||
wl_client* m_pClient = nullptr;
|
||||
|
||||
CHyprSignalListener destroy;
|
||||
|
||||
friend class CContentTypeProtocol;
|
||||
};
|
||||
|
||||
class CContentTypeProtocol : public IWaylandProtocol {
|
||||
public:
|
||||
CContentTypeProtocol(const wl_interface* iface, const int& ver, const std::string& name);
|
||||
|
||||
virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id);
|
||||
|
||||
SP<CContentType> getContentType(WP<CWLSurfaceResource> surface);
|
||||
|
||||
private:
|
||||
void destroyResource(CContentTypeManager* resource);
|
||||
void destroyResource(CContentType* resource);
|
||||
|
||||
std::vector<SP<CContentTypeManager>> m_vManagers;
|
||||
std::vector<SP<CContentType>> m_vContentTypes;
|
||||
|
||||
friend class CContentTypeManager;
|
||||
friend class CContentType;
|
||||
};
|
||||
|
||||
namespace PROTO {
|
||||
inline UP<CContentTypeProtocol> contentType;
|
||||
};
|
@@ -41,7 +41,7 @@ void CCursorShapeProtocol::createCursorShapeDevice(CWpCursorShapeManagerV1* pMgr
|
||||
}
|
||||
|
||||
void CCursorShapeProtocol::onSetShape(CWpCursorShapeDeviceV1* pMgr, uint32_t serial, wpCursorShapeDeviceV1Shape shape) {
|
||||
if UNLIKELY ((uint32_t)shape == 0 || (uint32_t)shape >= CURSOR_SHAPE_NAMES.size()) {
|
||||
if UNLIKELY ((uint32_t)shape == 0 || (uint32_t)shape > CURSOR_SHAPE_NAMES.size()) {
|
||||
pMgr->error(WP_CURSOR_SHAPE_DEVICE_V1_ERROR_INVALID_SHAPE, "The shape is invalid");
|
||||
return;
|
||||
}
|
||||
|
@@ -4,7 +4,6 @@
|
||||
#include "managers/eventLoop/EventLoopManager.hpp"
|
||||
#include <aquamarine/backend/DRM.hpp>
|
||||
#include <fcntl.h>
|
||||
using namespace Hyprutils::OS;
|
||||
|
||||
CDRMLeaseResource::CDRMLeaseResource(SP<CWpDrmLeaseV1> resource_, SP<CDRMLeaseRequestResource> request) : resource(resource_) {
|
||||
if UNLIKELY (!good())
|
||||
@@ -186,14 +185,15 @@ CDRMLeaseDeviceResource::CDRMLeaseDeviceResource(SP<CWpDrmLeaseDeviceV1> resourc
|
||||
RESOURCE->parent = self;
|
||||
});
|
||||
|
||||
CFileDescriptor fd{((Aquamarine::CDRMBackend*)PROTO::lease->primaryDevice->backend.get())->getNonMasterFD()};
|
||||
if (!fd.isValid()) {
|
||||
int fd = ((Aquamarine::CDRMBackend*)PROTO::lease->primaryDevice->backend.get())->getNonMasterFD();
|
||||
if (fd < 0) {
|
||||
LOGM(ERR, "Failed to dup fd in lease");
|
||||
return;
|
||||
}
|
||||
|
||||
LOGM(LOG, "Sending DRMFD {} to new lease device", fd.get());
|
||||
resource->sendDrmFd(fd.get());
|
||||
LOGM(LOG, "Sending DRMFD {} to new lease device", fd);
|
||||
resource->sendDrmFd(fd);
|
||||
close(fd);
|
||||
|
||||
for (auto const& m : PROTO::lease->primaryDevice->offeredOutputs) {
|
||||
if (m)
|
||||
@@ -231,15 +231,16 @@ void CDRMLeaseDeviceResource::sendConnector(PHLMONITOR monitor) {
|
||||
}
|
||||
|
||||
CDRMLeaseDevice::CDRMLeaseDevice(SP<Aquamarine::CDRMBackend> drmBackend) : backend(drmBackend) {
|
||||
auto drm = (Aquamarine::CDRMBackend*)drmBackend.get();
|
||||
auto drm = (Aquamarine::CDRMBackend*)drmBackend.get();
|
||||
|
||||
CFileDescriptor fd{drm->getNonMasterFD()};
|
||||
auto fd = drm->getNonMasterFD();
|
||||
|
||||
if (!fd.isValid()) {
|
||||
if (fd < 0) {
|
||||
LOGM(ERR, "Failed to dup fd for drm node {}", drm->gpuName);
|
||||
return;
|
||||
}
|
||||
|
||||
close(fd);
|
||||
success = true;
|
||||
name = drm->gpuName;
|
||||
}
|
||||
|
@@ -5,7 +5,6 @@
|
||||
#include "WaylandProtocol.hpp"
|
||||
#include "drm-lease-v1.hpp"
|
||||
#include "../helpers/signal/Signal.hpp"
|
||||
#include <hyprutils/os/FileDescriptor.hpp>
|
||||
|
||||
/*
|
||||
TODO: this protocol is not made for systems with multiple DRM nodes (e.g. multigpu)
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user