Merge branch 'hyprwm:main' into main
19
.github/ISSUE_TEMPLATE/bug.yml
vendored
|
@ -2,12 +2,13 @@ name: Bug Report
|
|||
description: Something is not working right
|
||||
labels: ["bug"]
|
||||
body:
|
||||
- type: markdown
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
value: |
|
||||
## Before opening a new issue, please take a moment to search through the current open and closed issues to check if it already exists.
|
||||
|
||||
---
|
||||
label: Already reported ? *
|
||||
description: Before opening a new bug report, please take a moment to search through the current open and closed issues to check if it already exists.
|
||||
options:
|
||||
- label: I have searched the existing open and closed issues.
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
id: type
|
||||
|
@ -28,10 +29,10 @@ body:
|
|||
attributes:
|
||||
label: System Info and Version
|
||||
description: |
|
||||
Paste the output of `hyprctl systeminfo -c` here (If you are on a
|
||||
version that shows you help menu, omit the `-c` and attach config files
|
||||
to the issue). If you have configs outside of the main config shown
|
||||
here, please attach.
|
||||
Paste the output of `hyprctl systeminfo -c` here. If you can't
|
||||
launch Hyprland, paste the output of `Hyprland --systeminfo`.
|
||||
If `Hyprland --systeminfo` errors out (added in 0.44.0), find
|
||||
and paste the Hyprland version manually.
|
||||
value: "<details>
|
||||
<summary>System/Version info</summary>
|
||||
|
||||
|
|
16
.github/workflows/nix-build.yml
vendored
|
@ -1,3 +1,5 @@
|
|||
name: Nix (Build)
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
secrets:
|
||||
|
@ -10,21 +12,17 @@ jobs:
|
|||
matrix:
|
||||
package:
|
||||
- hyprland
|
||||
- hyprland-cross
|
||||
- xdg-desktop-portal-hyprland
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Clone repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.ref }}
|
||||
submodules: recursive
|
||||
|
||||
- uses: cachix/install-nix-action@v27
|
||||
- uses: DeterminateSystems/nix-installer-action@main
|
||||
- uses: DeterminateSystems/magic-nix-cache-action@main
|
||||
|
||||
- uses: cachix/cachix-action@v15
|
||||
with:
|
||||
name: hyprland
|
||||
authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
|
||||
authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}"
|
||||
|
||||
- run: nix build '.?submodules=1#${{ matrix.package }}' -L --extra-substituters "https://hyprland.cachix.org"
|
||||
- run: nix build 'github:hyprwm/Hyprland?ref=${{ github.ref }}#${{ matrix.package }}' -L --extra-substituters "https://hyprland.cachix.org"
|
||||
|
|
7
.github/workflows/nix-ci.yml
vendored
|
@ -1,15 +1,14 @@
|
|||
name: Nix
|
||||
name: Nix (CI)
|
||||
|
||||
on: [push, pull_request, workflow_dispatch]
|
||||
|
||||
jobs:
|
||||
update-inputs:
|
||||
if: github.event_name == 'push' || github.event_name == 'workflow_dispatch'
|
||||
if: (github.event_name == 'push' || github.event_name == 'workflow_dispatch')
|
||||
uses: ./.github/workflows/nix-update-inputs.yml
|
||||
secrets: inherit
|
||||
|
||||
build:
|
||||
if: (github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork) && !contains(needs.*.result, 'failure')
|
||||
needs: update-inputs
|
||||
if: (github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork)
|
||||
uses: ./.github/workflows/nix-build.yml
|
||||
secrets: inherit
|
||||
|
|
3
.github/workflows/nix-update-inputs.yml
vendored
|
@ -1,4 +1,4 @@
|
|||
name: Nix
|
||||
name: Nix (Update Inputs)
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
|
@ -8,6 +8,7 @@ on:
|
|||
|
||||
jobs:
|
||||
update:
|
||||
if: github.repository == 'hyprwm/Hyprland'
|
||||
name: inputs
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
|
|
1
.github/workflows/release.yaml
vendored
|
@ -20,7 +20,6 @@ jobs:
|
|||
run: |
|
||||
git fetch --unshallow || echo "failed unshallowing"
|
||||
bash -c scripts/generateVersion.sh
|
||||
mv scripts/generateVersion.sh scripts/generateVersion.sh.bak
|
||||
|
||||
- name: Create tarball with submodules
|
||||
id: tar
|
||||
|
|
8
.github/workflows/stale.yml
vendored
|
@ -7,12 +7,12 @@ name: Mark stale issues and pull requests
|
|||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '7 */4 * * *'
|
||||
- cron: "7 */4 * * *"
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
stale:
|
||||
|
||||
if: github.repository == 'hyprwm/Hyprland'
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
issues: write
|
||||
|
@ -22,7 +22,7 @@ jobs:
|
|||
- uses: actions/stale@v5
|
||||
with:
|
||||
repo-token: ${{ secrets.STALEBOT_PAT }}
|
||||
stale-issue-label: 'stale'
|
||||
stale-pr-label: 'stale'
|
||||
stale-issue-label: "stale"
|
||||
stale-pr-label: "stale"
|
||||
operations-per-run: 40
|
||||
days-before-close: -1
|
||||
|
|
6
.gitignore
vendored
|
@ -14,6 +14,7 @@ _deps
|
|||
|
||||
build/
|
||||
result*
|
||||
/.pre-commit-config.yaml
|
||||
/.vscode/
|
||||
/.idea/
|
||||
.envrc
|
||||
|
@ -37,3 +38,8 @@ gmon.out
|
|||
PKGBUILD
|
||||
|
||||
src/version.h
|
||||
hyprpm/Makefile
|
||||
hyprctl/Makefile
|
||||
|
||||
**/.#*.*
|
||||
**/#*.*#
|
||||
|
|
103
CMakeLists.txt
|
@ -1,4 +1,4 @@
|
|||
cmake_minimum_required(VERSION 3.27)
|
||||
cmake_minimum_required(VERSION 3.30)
|
||||
|
||||
# Get version
|
||||
file(READ "${CMAKE_SOURCE_DIR}/VERSION" VER_RAW)
|
||||
|
@ -25,8 +25,18 @@ message(STATUS "Gathering git info")
|
|||
execute_process(COMMAND ./scripts/generateVersion.sh
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
|
||||
|
||||
# udis
|
||||
find_package(PkgConfig REQUIRED)
|
||||
|
||||
# Try to find canihavesomecoffee's udis86 using pkgconfig vmd/udis86 does not
|
||||
# provide a .pc file and won't be detected this way
|
||||
pkg_check_modules(udis_dep IMPORTED_TARGET udis86>=1.7.2)
|
||||
|
||||
# Fallback to subproject
|
||||
if(NOT udis_dep_FOUND)
|
||||
add_subdirectory("subprojects/udis86")
|
||||
include_directories("subprojects/udis86")
|
||||
message(STATUS "udis86 dependency not found, falling back to subproject")
|
||||
endif()
|
||||
|
||||
if(CMAKE_BUILD_TYPE)
|
||||
string(TOLOWER ${CMAKE_BUILD_TYPE} BUILDTYPE_LOWER)
|
||||
|
@ -47,11 +57,11 @@ else()
|
|||
set(BUILDTYPE_LOWER "release")
|
||||
endif()
|
||||
|
||||
find_package(PkgConfig REQUIRED)
|
||||
|
||||
pkg_get_variable(WAYLAND_PROTOCOLS_DIR wayland-protocols pkgdatadir)
|
||||
message(STATUS "Found wayland-protocols at ${WAYLAND_PROTOCOLS_DIR}")
|
||||
pkg_get_variable(WAYLAND_SERVER_DIR wayland-server pkgdatadir)
|
||||
pkg_get_variable(WAYLAND_SCANNER_PKGDATA_DIR wayland-scanner pkgdatadir)
|
||||
message(
|
||||
STATUS "Found wayland-scanner pkgdatadir at ${WAYLAND_SCANNER_PKGDATA_DIR}")
|
||||
|
||||
if(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG)
|
||||
message(STATUS "Configuring Hyprland in Debug with CMake")
|
||||
|
@ -61,8 +71,11 @@ else()
|
|||
message(STATUS "Configuring Hyprland in Release with CMake")
|
||||
endif()
|
||||
|
||||
include_directories(. "src/" "subprojects/udis86/" "protocols/")
|
||||
set(CMAKE_CXX_STANDARD 23)
|
||||
add_compile_definitions(HYPRLAND_VERSION="${HYPRLAND_VERSION}")
|
||||
|
||||
include_directories(. "src/" "protocols/")
|
||||
|
||||
set(CMAKE_CXX_STANDARD 26)
|
||||
add_compile_options(
|
||||
-Wall
|
||||
-Wextra
|
||||
|
@ -87,16 +100,19 @@ else()
|
|||
endif()
|
||||
find_package(OpenGL REQUIRED COMPONENTS ${GLES_VERSION})
|
||||
|
||||
pkg_check_modules(hyprctl_deps REQUIRED IMPORTED_TARGET hyprutils>=0.2.1)
|
||||
|
||||
pkg_check_modules(aquamarine_dep REQUIRED IMPORTED_TARGET aquamarine>=0.4.2)
|
||||
|
||||
add_compile_definitions(AQUAMARINE_VERSION="${aquamarine_dep_VERSION}")
|
||||
|
||||
pkg_check_modules(
|
||||
deps
|
||||
REQUIRED
|
||||
IMPORTED_TARGET
|
||||
aquamarine
|
||||
xkbcommon
|
||||
uuid
|
||||
wayland-server
|
||||
wayland-client
|
||||
wayland-cursor
|
||||
wayland-server>=1.22.90
|
||||
wayland-protocols
|
||||
cairo
|
||||
pango
|
||||
|
@ -105,15 +121,11 @@ pkg_check_modules(
|
|||
xcursor
|
||||
libdrm
|
||||
libinput
|
||||
hwdata
|
||||
libseat
|
||||
libdisplay-info
|
||||
libliftoff
|
||||
libudev
|
||||
gbm
|
||||
gio-2.0
|
||||
hyprlang>=0.3.2
|
||||
hyprcursor>=0.1.7
|
||||
hyprutils>=0.2.1)
|
||||
hyprutils>=0.2.3)
|
||||
|
||||
find_package(hyprwayland-scanner 0.3.10 REQUIRED)
|
||||
|
||||
|
@ -195,14 +207,11 @@ else()
|
|||
REQUIRED
|
||||
IMPORTED_TARGET
|
||||
xcb
|
||||
xwayland
|
||||
xcb-util
|
||||
xcb-render
|
||||
xcb-xfixes
|
||||
xcb-icccm
|
||||
xcb-composite
|
||||
xcb-res
|
||||
xcb-ewmh
|
||||
xcb-errors)
|
||||
target_link_libraries(Hyprland PkgConfig::xdeps)
|
||||
endif()
|
||||
|
@ -225,14 +234,19 @@ target_precompile_headers(Hyprland PRIVATE
|
|||
|
||||
message(STATUS "Setting link libraries")
|
||||
|
||||
target_link_libraries(Hyprland rt PkgConfig::deps)
|
||||
target_link_libraries(Hyprland rt PkgConfig::aquamarine_dep PkgConfig::deps)
|
||||
if(udis_dep_FOUND)
|
||||
target_link_libraries(Hyprland PkgConfig::udis_dep)
|
||||
else()
|
||||
target_link_libraries(Hyprland libudis86)
|
||||
endif()
|
||||
|
||||
# used by `make installheaders`, to ensure the headers are generated
|
||||
add_custom_target(generate-protocol-headers)
|
||||
|
||||
function(protocolnew protoPath protoName external)
|
||||
if(external)
|
||||
set(path ${CMAKE_SOURCE_DIR}/${protoPath})
|
||||
set(path ${protoPath})
|
||||
else()
|
||||
set(path ${WAYLAND_PROTOCOLS_DIR}/${protoPath})
|
||||
endif()
|
||||
|
@ -251,22 +265,31 @@ function(protocolWayland)
|
|||
add_custom_command(
|
||||
OUTPUT ${CMAKE_SOURCE_DIR}/protocols/wayland.cpp
|
||||
${CMAKE_SOURCE_DIR}/protocols/wayland.hpp
|
||||
COMMAND hyprwayland-scanner --wayland-enums
|
||||
${WAYLAND_SERVER_DIR}/wayland.xml ${CMAKE_SOURCE_DIR}/protocols/
|
||||
COMMAND
|
||||
hyprwayland-scanner --wayland-enums
|
||||
${WAYLAND_SCANNER_PKGDATA_DIR}/wayland.xml ${CMAKE_SOURCE_DIR}/protocols/
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
|
||||
target_sources(Hyprland PRIVATE protocols/wayland.cpp protocols/wayland.hpp)
|
||||
target_sources(generate-protocol-headers
|
||||
PRIVATE ${CMAKE_SOURCE_DIR}/protocols/wayland.hpp)
|
||||
endfunction()
|
||||
|
||||
target_link_libraries(Hyprland OpenGL::EGL OpenGL::GL Threads::Threads
|
||||
libudis86 uuid)
|
||||
target_link_libraries(Hyprland OpenGL::EGL OpenGL::GL Threads::Threads)
|
||||
|
||||
protocolnew("subprojects/hyprland-protocols/protocols"
|
||||
"hyprland-global-shortcuts-v1" true)
|
||||
pkg_check_modules(hyprland_protocols_dep hyprland-protocols>=0.4.0)
|
||||
if(hyprland_protocols_dep_FOUND)
|
||||
pkg_get_variable(HYPRLAND_PROTOCOLS hyprland-protocols pkgdatadir)
|
||||
message(STATUS "hyprland-protocols dependency set to ${HYPRLAND_PROTOCOLS}")
|
||||
else()
|
||||
set(HYPRLAND_PROTOCOLS "subprojects/hyprland-protocols")
|
||||
message(STATUS "hyprland-protocols subproject set to ${HYPRLAND_PROTOCOLS}")
|
||||
endif()
|
||||
|
||||
protocolnew("${HYPRLAND_PROTOCOLS}/protocols" "hyprland-global-shortcuts-v1"
|
||||
true)
|
||||
protocolnew("unstable/text-input" "text-input-unstable-v1" false)
|
||||
protocolnew("subprojects/hyprland-protocols/protocols"
|
||||
"hyprland-toplevel-export-v1" true)
|
||||
protocolnew("${HYPRLAND_PROTOCOLS}/protocols" "hyprland-toplevel-export-v1"
|
||||
true)
|
||||
protocolnew("protocols" "wlr-screencopy-unstable-v1" true)
|
||||
protocolnew("protocols" "wlr-gamma-control-unstable-v1" true)
|
||||
protocolnew("protocols" "wlr-foreign-toplevel-management-unstable-v1" true)
|
||||
|
@ -277,10 +300,11 @@ protocolnew("protocols" "input-method-unstable-v2" true)
|
|||
protocolnew("protocols" "wlr-output-management-unstable-v1" true)
|
||||
protocolnew("protocols" "kde-server-decoration" true)
|
||||
protocolnew("protocols" "wlr-data-control-unstable-v1" true)
|
||||
protocolnew("subprojects/hyprland-protocols/protocols" "hyprland-focus-grab-v1"
|
||||
true)
|
||||
protocolnew("${HYPRLAND_PROTOCOLS}/protocols" "hyprland-focus-grab-v1" true)
|
||||
protocolnew("protocols" "wlr-layer-shell-unstable-v1" true)
|
||||
protocolnew("protocols" "wayland-drm" true)
|
||||
protocolnew("${HYPRLAND_PROTOCOLS}/protocols" "hyprland-ctm-control-v1" true)
|
||||
|
||||
protocolnew("staging/tearing-control" "tearing-control-v1" false)
|
||||
protocolnew("staging/fractional-scale" "fractional-scale-v1" false)
|
||||
protocolnew("unstable/xdg-output" "xdg-output-unstable-v1" false)
|
||||
|
@ -309,6 +333,9 @@ protocolnew("stable/viewporter" "viewporter" false)
|
|||
protocolnew("stable/linux-dmabuf" "linux-dmabuf-v1" false)
|
||||
protocolnew("staging/drm-lease" "drm-lease-v1" false)
|
||||
protocolnew("staging/linux-drm-syncobj" "linux-drm-syncobj-v1" false)
|
||||
protocolnew("staging/xdg-dialog" "xdg-dialog-v1" false)
|
||||
protocolnew("staging/single-pixel-buffer" "single-pixel-buffer-v1" false)
|
||||
protocolnew("staging/security-context" "security-context-v1" false)
|
||||
|
||||
protocolwayland()
|
||||
|
||||
|
@ -323,19 +350,21 @@ install(
|
|||
CODE "execute_process( \
|
||||
COMMAND ${CMAKE_COMMAND} -E create_symlink \
|
||||
${CMAKE_INSTALL_FULL_BINDIR}/Hyprland \
|
||||
${CMAKE_INSTALL_FULL_BINDIR}/hyprland
|
||||
\"\$ENV{DESTDIR}${CMAKE_INSTALL_FULL_BINDIR}/hyprland\" \
|
||||
)")
|
||||
|
||||
# session file
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/example/hyprland.desktop
|
||||
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/wayland-sessions)
|
||||
|
||||
# allow Hyprland to find wallpapers
|
||||
# allow Hyprland to find assets
|
||||
add_compile_definitions(DATAROOTDIR="${CMAKE_INSTALL_FULL_DATAROOTDIR}")
|
||||
|
||||
# wallpapers
|
||||
file(GLOB_RECURSE WALLPAPERS "assets/wall*")
|
||||
install(FILES ${WALLPAPERS} DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/hypr)
|
||||
# installable assets
|
||||
file(GLOB_RECURSE INSTALLABLE_ASSETS "assets/install/*")
|
||||
list(FILTER INSTALLABLE_ASSETS EXCLUDE REGEX "meson.build")
|
||||
install(FILES ${INSTALLABLE_ASSETS}
|
||||
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/hypr)
|
||||
|
||||
# default config
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/example/hyprland.conf
|
||||
|
|
28
Makefile
|
@ -1,28 +1,24 @@
|
|||
PREFIX = /usr/local
|
||||
|
||||
legacyrenderer:
|
||||
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -DLEGACY_RENDERER:BOOL=true -S . -B ./build -G Ninja
|
||||
cmake --build ./build --config Release --target all
|
||||
chmod -R 777 ./build
|
||||
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -DLEGACY_RENDERER:BOOL=true -S . -B ./build
|
||||
cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
|
||||
|
||||
legacyrendererdebug:
|
||||
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Debug -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -DLEGACY_RENDERER:BOOL=true -S . -B ./build -G Ninja
|
||||
cmake --build ./build --config Release --target all
|
||||
chmod -R 777 ./build
|
||||
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Debug -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -DLEGACY_RENDERER:BOOL=true -S . -B ./build
|
||||
cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
|
||||
|
||||
release:
|
||||
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -S . -B ./build -G Ninja
|
||||
cmake --build ./build --config Release --target all
|
||||
chmod -R 777 ./build
|
||||
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -S . -B ./build
|
||||
cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
|
||||
|
||||
debug:
|
||||
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Debug -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -S . -B ./build -G Ninja
|
||||
cmake --build ./build --config Debug --target all
|
||||
chmod -R 777 ./build
|
||||
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Debug -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -S . -B ./build
|
||||
cmake --build ./build --config Debug --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
|
||||
|
||||
nopch:
|
||||
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -DCMAKE_DISABLE_PRECOMPILE_HEADERS=ON -S . -B ./build -G Ninja
|
||||
cmake --build ./build --config Release --target all
|
||||
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -DCMAKE_DISABLE_PRECOMPILE_HEADERS=ON -S . -B ./build
|
||||
cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
|
||||
|
||||
clear:
|
||||
rm -rf build
|
||||
|
@ -87,8 +83,8 @@ asan:
|
|||
#git reset --hard
|
||||
|
||||
@echo -en "If you want to apply a patch, input its path (leave empty for none):\n"
|
||||
@read patchvar
|
||||
@if [-n "$patchvar"]; then patch -p1 < $patchvar || echo ""; else echo "No patch specified"; fi
|
||||
@read patchvar; \
|
||||
if [ -n "$$patchvar" ]; then patch -p1 < "$$patchvar" || echo ""; else echo "No patch specified"; fi
|
||||
|
||||
git clone --recursive https://gitlab.freedesktop.org/wayland/wayland
|
||||
cd wayland && patch -p1 < ../scripts/waylandStatic.diff && meson setup build --buildtype=debug -Db_sanitize=address -Ddocumentation=false && ninja -C build && cd ..
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<div align = center>
|
||||
|
||||
<img src="https://raw.githubusercontent.com/vaxerski/Hyprland/main/assets/header.svg" width="750" height="300" alt="banner">
|
||||
<img src="https://raw.githubusercontent.com/hyprwm/Hyprland/main/assets/header.svg" width="750" height="300" alt="banner">
|
||||
|
||||
<br>
|
||||
|
||||
|
@ -125,7 +125,6 @@ easy IPC, much more QoL stuff than other compositors and more...
|
|||
|
||||
<!----------------------------------{ Images }--------------------------------->
|
||||
|
||||
[Stars Preview]: https://starchart.cc/vaxerski/Hyprland.svg
|
||||
[Preview A]: https://i.ibb.co/C1yTb0r/falf.png
|
||||
[Preview B]: https://linfindel.github.io/cdn/hyprland-preview-b.png
|
||||
[Preview C]: https://i.ibb.co/B3GJg28/20221126-20h53m26s-grim.png
|
||||
|
|
2
VERSION
|
@ -1 +1 @@
|
|||
0.41.2
|
||||
0.44.0
|
||||
|
|
BIN
assets/install/lockdead.png
Normal file
After Width: | Height: | Size: 110 KiB |
BIN
assets/install/lockdead2.png
Normal file
After Width: | Height: | Size: 48 KiB |
10
assets/install/meson.build
Normal file
|
@ -0,0 +1,10 @@
|
|||
globber = run_command('sh', '-c', 'find . -type f -not -name "*.build"', check: true)
|
||||
files = globber.stdout().strip().split('\n')
|
||||
|
||||
foreach file : files
|
||||
install_data(
|
||||
file,
|
||||
install_dir: join_paths(get_option('datadir'), 'hypr'),
|
||||
install_tag: 'runtime',
|
||||
)
|
||||
endforeach
|
Before Width: | Height: | Size: 14 MiB After Width: | Height: | Size: 14 MiB |
Before Width: | Height: | Size: 5.9 MiB After Width: | Height: | Size: 5.9 MiB |
Before Width: | Height: | Size: 27 MiB After Width: | Height: | Size: 27 MiB |
|
@ -1,7 +1,7 @@
|
|||
wallpapers = ['0', '1', '2']
|
||||
install_data(
|
||||
'hyprland-portals.conf',
|
||||
install_dir: join_paths(get_option('datadir'), 'xdg-desktop-portal'),
|
||||
install_tag: 'runtime',
|
||||
)
|
||||
|
||||
foreach type : wallpapers
|
||||
install_data(f'wall@type@.png', install_dir: join_paths(get_option('datadir'), 'hypr'), install_tag: 'runtime')
|
||||
endforeach
|
||||
|
||||
install_data('hyprland-portals.conf', install_dir: join_paths(get_option('datadir'), 'xdg-desktop-portal'), install_tag: 'runtime')
|
||||
subdir('install')
|
||||
|
|
|
@ -10,8 +10,8 @@ Hyprland - Dynamic tiling Wayland compositor
|
|||
\f[B]Hyprland\f[R] [\f[I]arg [...]\f[R]].
|
||||
.SH DESCRIPTION
|
||||
.PP
|
||||
\f[B]Hyprland\f[R] is a dynamic tiling Wayland compositor based on
|
||||
wlroots that doesn\[aq]t sacrifice on its looks.
|
||||
\f[B]Hyprland\f[R] is an independent, highly customizable, dynamic
|
||||
tiling Wayland compositor that doesn\[aq]t sacrifice on its looks.
|
||||
.PP
|
||||
You can launch Hyprland by either going into a TTY and executing
|
||||
\f[B]Hyprland\f[R], or with a login manager.
|
||||
|
|
|
@ -14,8 +14,8 @@ SYNOPSIS
|
|||
DESCRIPTION
|
||||
===========
|
||||
|
||||
**Hyprland** is a dynamic tiling Wayland compositor based on
|
||||
wlroots that doesn't sacrifice on its looks.
|
||||
**Hyprland** is an independent, highly customizable,
|
||||
dynamic tiling Wayland compositor that doesn't sacrifice on its looks.
|
||||
|
||||
You can launch Hyprland by either going into a TTY and
|
||||
executing **Hyprland**, or with a login manager.
|
||||
|
|
14
example/hyprland-session.service
Normal file
|
@ -0,0 +1,14 @@
|
|||
[Unit]
|
||||
Description=Hyprland - Tiling compositor with the looks
|
||||
Documentation=man:Hyprland(1)
|
||||
BindsTo=graphical-session.target
|
||||
Before=graphical-session.target
|
||||
Wants=graphical-session-pre.target
|
||||
After=graphical-session-pre.target
|
||||
|
||||
[Service]
|
||||
Type=notify
|
||||
ExecStart=/usr/bin/Hyprland
|
||||
ExecStop=/usr/bin/hyprctl dispatch exit
|
||||
Restart=on-failure
|
||||
Slice=session.slice
|
5
example/hyprland-systemd.desktop
Normal file
|
@ -0,0 +1,5 @@
|
|||
[Desktop Entry]
|
||||
Name=Hyprland
|
||||
Comment=An intelligent dynamic tiling Wayland compositor
|
||||
Exec=systemctl --user start --wait hyprland-session
|
||||
Type=Application
|
|
@ -117,6 +117,13 @@ animations {
|
|||
animation = workspaces, 1, 6, default
|
||||
}
|
||||
|
||||
# Ref https://wiki.hyprland.org/Configuring/Workspace-Rules/
|
||||
# "Smart gaps" / "No gaps when only"
|
||||
# uncomment all three if you wish to use that.
|
||||
# workspace = w[t1], gapsout:0, gapsin:0, border: 0, rounding:0
|
||||
# workspace = w[tg1], gapsout:0, gapsin:0, border: 0, rounding:0
|
||||
# workspace = f[1], gapsout:0, gapsin:0, border: 0, rounding:0
|
||||
|
||||
# See https://wiki.hyprland.org/Configuring/Dwindle-Layout/ for more
|
||||
dwindle {
|
||||
pseudotile = true # Master switch for pseudotiling. Enabling is bound to mainMod + P in the keybinds section below
|
||||
|
@ -169,9 +176,9 @@ device {
|
|||
}
|
||||
|
||||
|
||||
####################
|
||||
### KEYBINDINGSS ###
|
||||
####################
|
||||
###################
|
||||
### KEYBINDINGS ###
|
||||
###################
|
||||
|
||||
# See https://wiki.hyprland.org/Configuring/Keywords/
|
||||
$mainMod = SUPER # Sets "Windows" key as main modifier
|
||||
|
@ -228,6 +235,19 @@ bind = $mainMod, mouse_up, workspace, e-1
|
|||
bindm = $mainMod, mouse:272, movewindow
|
||||
bindm = $mainMod, mouse:273, resizewindow
|
||||
|
||||
# Laptop multimedia keys for volume and LCD brightness
|
||||
bindel = ,XF86AudioRaiseVolume, exec, wpctl set-volume -l 1 @DEFAULT_AUDIO_SINK@ 5%+
|
||||
bindel = ,XF86AudioLowerVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%-
|
||||
bindel = ,XF86AudioMute, exec, wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle
|
||||
bindel = ,XF86AudioMicMute, exec, wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle
|
||||
bindel = ,XF86MonBrightnessUp, exec, brightnessctl s 10%+
|
||||
bindel = ,XF86MonBrightnessDown, exec, brightnessctl s 10%-
|
||||
|
||||
# Requires playerctl
|
||||
bindl = , XF86AudioNext, exec, playerctl next
|
||||
bindl = , XF86AudioPause, exec, playerctl play-pause
|
||||
bindl = , XF86AudioPlay, exec, playerctl play-pause
|
||||
bindl = , XF86AudioPrev, exec, playerctl previous
|
||||
|
||||
##############################
|
||||
### WINDOWS AND WORKSPACES ###
|
||||
|
@ -242,4 +262,8 @@ bindm = $mainMod, mouse:273, resizewindow
|
|||
# Example windowrule v2
|
||||
# windowrulev2 = float,class:^(kitty)$,title:^(kitty)$
|
||||
|
||||
windowrulev2 = suppressevent maximize, class:.* # You'll probably like this.
|
||||
# Ignore maximize requests from apps. You'll probably like this.
|
||||
windowrulev2 = suppressevent maximize, class:.*
|
||||
|
||||
# Fix some dragging issues with XWayland
|
||||
windowrulev2 = nofocus,class:^$,title:^$,xwayland:1,floating:1,fullscreen:0,pinned:0
|
||||
|
|
|
@ -3,3 +3,5 @@ Name=Hyprland
|
|||
Comment=An intelligent dynamic tiling Wayland compositor
|
||||
Exec=Hyprland
|
||||
Type=Application
|
||||
DesktopNames=Hyprland
|
||||
Keywords=tiling;wayland;compositor;
|
||||
|
|
|
@ -1,2 +1,10 @@
|
|||
install_data('hyprland.conf', install_dir: join_paths(get_option('datadir'), 'hypr'), install_tag: 'runtime')
|
||||
install_data('hyprland.desktop', install_dir: join_paths(get_option('datadir'), 'wayland-sessions'), install_tag: 'runtime')
|
||||
install_data(
|
||||
'hyprland.conf',
|
||||
install_dir: join_paths(get_option('datadir'), 'hypr'),
|
||||
install_tag: 'runtime',
|
||||
)
|
||||
install_data(
|
||||
'hyprland.desktop',
|
||||
install_dir: join_paths(get_option('datadir'), 'wayland-sessions'),
|
||||
install_tag: 'runtime',
|
||||
)
|
||||
|
|
138
flake.lock
|
@ -16,11 +16,11 @@
|
|||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1722347739,
|
||||
"narHash": "sha256-rAoh+K6KG+b1DwSWtqRVocdojnH6nGk6q07mNltoUSM=",
|
||||
"lastModified": 1728902391,
|
||||
"narHash": "sha256-44bnoY0nAvbBQ/lVjmn511yL39Sv7SknV0BDxn34P3Q=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "aquamarine",
|
||||
"rev": "7c3565f9bedc7cb601cc0baa14792247e4dc1d5a",
|
||||
"rev": "9874e08eec85b5542ca22494e127b0cdce46b786",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -29,6 +29,43 @@
|
|||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-compat": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1696426674,
|
||||
"narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=",
|
||||
"owner": "edolstra",
|
||||
"repo": "flake-compat",
|
||||
"rev": "0f9255e01c2351cc7d116c072cb317785dd33b33",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "edolstra",
|
||||
"repo": "flake-compat",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"gitignore": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"pre-commit-hooks",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1709087332,
|
||||
"narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=",
|
||||
"owner": "hercules-ci",
|
||||
"repo": "gitignore.nix",
|
||||
"rev": "637db329424fd7e46cf4185293b9cc8c88c95394",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "hercules-ci",
|
||||
"repo": "gitignore.nix",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"hyprcursor": {
|
||||
"inputs": {
|
||||
"hyprlang": [
|
||||
|
@ -42,11 +79,11 @@
|
|||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1721330371,
|
||||
"narHash": "sha256-aYlHTWylczLt6ERJyg6E66Y/XSCbVL7leVcRuJmVbpI=",
|
||||
"lastModified": 1728669738,
|
||||
"narHash": "sha256-EDNAU9AYcx8OupUzbTbWE1d3HYdeG0wO6Msg3iL1muk=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "hyprcursor",
|
||||
"rev": "4493a972b48f9c3014befbbf381ed5fff91a65dc",
|
||||
"rev": "0264e698149fcb857a66a53018157b41f8d97bb0",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -58,20 +95,18 @@
|
|||
"hyprland-protocols": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"xdph",
|
||||
"nixpkgs"
|
||||
],
|
||||
"systems": [
|
||||
"xdph",
|
||||
"systems"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1721326555,
|
||||
"narHash": "sha256-zCu4R0CSHEactW9JqYki26gy8h9f6rHmSwj4XJmlHgg=",
|
||||
"lastModified": 1728345020,
|
||||
"narHash": "sha256-xGbkc7U/Roe0/Cv3iKlzijIaFBNguasI31ynL2IlEoM=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "hyprland-protocols",
|
||||
"rev": "5a11232266bf1a1f5952d5b179c3f4b2facaaa84",
|
||||
"rev": "a7c183800e74f337753de186522b9017a07a8cee",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -93,11 +128,11 @@
|
|||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1721324361,
|
||||
"narHash": "sha256-BiJKO0IIdnSwHQBSrEJlKlFr753urkLE48wtt0UhNG4=",
|
||||
"lastModified": 1728168612,
|
||||
"narHash": "sha256-AnB1KfiXINmuiW7BALYrKqcjCnsLZPifhb/7BsfPbns=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "hyprlang",
|
||||
"rev": "adbefbf49664a6c2c8bf36b6487fd31e3eb68086",
|
||||
"rev": "f054f2e44d6a0b74607a6bc0f52dba337a3db38e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -116,11 +151,11 @@
|
|||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1722098849,
|
||||
"narHash": "sha256-D3wIZlBNh7LuZ0NaoCpY/Pvu+xHxIVtSN+KkWZYvvVs=",
|
||||
"lastModified": 1728941256,
|
||||
"narHash": "sha256-WRypmcZ2Bw94lLmcmxYokVOHPJSZ7T06V49QZ4tkZeQ=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "hyprutils",
|
||||
"rev": "5dcbbc1e3de40b2cecfd2007434d86e924468f1f",
|
||||
"rev": "fd4be8b9ca932f7384e454bcd923c5451ef2aa85",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -139,11 +174,11 @@
|
|||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1721324119,
|
||||
"narHash": "sha256-SOOqIT27/X792+vsLSeFdrNTF+OSRp5qXv6Te+fb2Qg=",
|
||||
"lastModified": 1726874836,
|
||||
"narHash": "sha256-VKR0sf0PSNCB0wPHVKSAn41mCNVCnegWmgkrneKDhHM=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "hyprwayland-scanner",
|
||||
"rev": "a048a6cb015340bd82f97c1f40a4b595ca85cc30",
|
||||
"rev": "500c81a9e1a76760371049a8d99e008ea77aa59e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -154,11 +189,11 @@
|
|||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1722185531,
|
||||
"narHash": "sha256-veKR07psFoJjINLC8RK4DiLniGGMgF3QMlS4tb74S6k=",
|
||||
"lastModified": 1728888510,
|
||||
"narHash": "sha256-nsNdSldaAyu6PE3YUA+YQLqUDJh+gRbBooMMekZJwvI=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "52ec9ac3b12395ad677e8b62106f0b98c1f8569d",
|
||||
"rev": "a3c0b3b21515f74fd2665903d4ce6bc4dc81c77c",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -168,14 +203,55 @@
|
|||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs-stable": {
|
||||
"locked": {
|
||||
"lastModified": 1720386169,
|
||||
"narHash": "sha256-NGKVY4PjzwAa4upkGtAMz1npHGoRzWotlSnVlqI40mo=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "194846768975b7ad2c4988bdb82572c00222c0d7",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixos-24.05",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"pre-commit-hooks": {
|
||||
"inputs": {
|
||||
"flake-compat": "flake-compat",
|
||||
"gitignore": "gitignore",
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
],
|
||||
"nixpkgs-stable": "nixpkgs-stable"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1728778939,
|
||||
"narHash": "sha256-WybK5E3hpGxtCYtBwpRj1E9JoiVxe+8kX83snTNaFHE=",
|
||||
"owner": "cachix",
|
||||
"repo": "git-hooks.nix",
|
||||
"rev": "ff68f91754be6f3427e4986d7949e6273659be1d",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "cachix",
|
||||
"repo": "git-hooks.nix",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"aquamarine": "aquamarine",
|
||||
"hyprcursor": "hyprcursor",
|
||||
"hyprland-protocols": "hyprland-protocols",
|
||||
"hyprlang": "hyprlang",
|
||||
"hyprutils": "hyprutils",
|
||||
"hyprwayland-scanner": "hyprwayland-scanner",
|
||||
"nixpkgs": "nixpkgs",
|
||||
"pre-commit-hooks": "pre-commit-hooks",
|
||||
"systems": "systems",
|
||||
"xdph": "xdph"
|
||||
}
|
||||
|
@ -197,10 +273,18 @@
|
|||
},
|
||||
"xdph": {
|
||||
"inputs": {
|
||||
"hyprland-protocols": "hyprland-protocols",
|
||||
"hyprland-protocols": [
|
||||
"hyprland-protocols"
|
||||
],
|
||||
"hyprlang": [
|
||||
"hyprlang"
|
||||
],
|
||||
"hyprutils": [
|
||||
"hyprutils"
|
||||
],
|
||||
"hyprwayland-scanner": [
|
||||
"hyprwayland-scanner"
|
||||
],
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
],
|
||||
|
@ -209,11 +293,11 @@
|
|||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1722365976,
|
||||
"narHash": "sha256-Khdm+mDzYA//XaU0M+hftod+rKr5q9SSHSEuiQ0/9ow=",
|
||||
"lastModified": 1728166987,
|
||||
"narHash": "sha256-w6dVTguAn9zJ+7aPOhBQgDz8bn6YZ7b56cY8Kg5HJRI=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "xdg-desktop-portal-hyprland",
|
||||
"rev": "7f2a77ddf60390248e2a3de2261d7102a13e5341",
|
||||
"rev": "fb9c8d665af0588bb087f97d0f673ddf0d501787",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
|
45
flake.nix
|
@ -22,6 +22,12 @@
|
|||
inputs.hyprlang.follows = "hyprlang";
|
||||
};
|
||||
|
||||
hyprland-protocols = {
|
||||
url = "github:hyprwm/hyprland-protocols";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
inputs.systems.follows = "systems";
|
||||
};
|
||||
|
||||
hyprlang = {
|
||||
url = "github:hyprwm/hyprlang";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
|
@ -45,7 +51,15 @@
|
|||
url = "github:hyprwm/xdg-desktop-portal-hyprland";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
inputs.systems.follows = "systems";
|
||||
inputs.hyprland-protocols.follows = "hyprland-protocols";
|
||||
inputs.hyprlang.follows = "hyprlang";
|
||||
inputs.hyprutils.follows = "hyprutils";
|
||||
inputs.hyprwayland-scanner.follows = "hyprwayland-scanner";
|
||||
};
|
||||
|
||||
pre-commit-hooks = {
|
||||
url = "github:cachix/git-hooks.nix";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -65,6 +79,15 @@
|
|||
hyprland-extras
|
||||
];
|
||||
});
|
||||
pkgsCrossFor = eachSystem (system: crossSystem:
|
||||
import nixpkgs {
|
||||
localSystem = system;
|
||||
inherit crossSystem;
|
||||
overlays = with self.overlays; [
|
||||
hyprland-packages
|
||||
hyprland-extras
|
||||
];
|
||||
});
|
||||
in {
|
||||
overlays = import ./nix/overlays.nix {inherit self lib inputs;};
|
||||
|
||||
|
@ -74,6 +97,18 @@
|
|||
self.packages.${system})
|
||||
// {
|
||||
inherit (self.packages.${system}) xdg-desktop-portal-hyprland;
|
||||
pre-commit-check = inputs.pre-commit-hooks.lib.${system}.run {
|
||||
src = ./.;
|
||||
hooks = {
|
||||
hyprland-treewide-formatter = {
|
||||
enable = true;
|
||||
entry = "${self.formatter.${system}}/bin/hyprland-treewide-formatter";
|
||||
pass_filenames = false;
|
||||
excludes = ["subprojects"];
|
||||
always_run = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
});
|
||||
|
||||
packages = eachSystem (system: {
|
||||
|
@ -90,25 +125,23 @@
|
|||
|
||||
xdg-desktop-portal-hyprland
|
||||
;
|
||||
hyprland-cross = (pkgsCrossFor.${system} "aarch64-linux").hyprland;
|
||||
});
|
||||
|
||||
devShells = eachSystem (system: {
|
||||
default =
|
||||
pkgsFor.${system}.mkShell.override {
|
||||
stdenv = pkgsFor.${system}.gcc13Stdenv;
|
||||
inherit (self.packages.${system}.default) stdenv;
|
||||
} {
|
||||
name = "hyprland-shell";
|
||||
nativeBuildInputs = with pkgsFor.${system}; [
|
||||
expat
|
||||
libxml2
|
||||
];
|
||||
hardeningDisable = ["fortify"];
|
||||
inputsFrom = [pkgsFor.${system}.hyprland];
|
||||
packages = [pkgsFor.${system}.clang-tools];
|
||||
inherit (self.checks.${system}.pre-commit-check) shellHook;
|
||||
};
|
||||
});
|
||||
|
||||
formatter = eachSystem (system: nixpkgs.legacyPackages.${system}.alejandra);
|
||||
formatter = eachSystem (system: pkgsFor.${system}.callPackage ./nix/formatter.nix {});
|
||||
|
||||
nixosModules.default = import ./nix/module.nix inputs;
|
||||
homeManagerModules.default = import ./nix/hm-module.nix self;
|
||||
|
|
|
@ -9,7 +9,7 @@ pkg_check_modules(deps REQUIRED IMPORTED_TARGET hyprutils>=0.1.1)
|
|||
|
||||
add_executable(hyprctl "main.cpp")
|
||||
|
||||
target_link_libraries(hyprctl PUBLIC PkgConfig::deps)
|
||||
target_link_libraries(hyprctl PUBLIC PkgConfig::hyprctl_deps)
|
||||
|
||||
# binary
|
||||
install(TARGETS hyprctl)
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
all:
|
||||
$(CXX) $(CXXFLAGS) -std=c++2b ./main.cpp -o ./hyprctl
|
||||
clean:
|
||||
rm ./hyprctl
|
|
@ -1,5 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <string_view>
|
||||
|
||||
const std::string_view USAGE = R"#(usage: hyprctl [flags] <command> [args...|--help]
|
||||
|
||||
commands:
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
_hyprctl_cmd_2 () {
|
||||
_hyprctl_cmd_1 () {
|
||||
hyprctl monitors | awk '/Monitor/{ print $2 }'
|
||||
}
|
||||
|
||||
_hyprctl_cmd_3 () {
|
||||
hyprpm list | awk '/Plugin/{ print $4 }'
|
||||
}
|
||||
|
||||
_hyprctl_cmd_0 () {
|
||||
hyprctl clients | awk '/class/{print $2}'
|
||||
}
|
||||
|
||||
_hyprctl_cmd_1 () {
|
||||
_hyprctl_cmd_2 () {
|
||||
hyprctl devices | sed -n '/Keyboard at/{n; s/^\s\+//; p}'
|
||||
}
|
||||
|
||||
_hyprctl_cmd_0 () {
|
||||
hyprpm list | awk '/Plugin/{print $4}'
|
||||
}
|
||||
|
||||
_hyprctl () {
|
||||
if [[ $(type -t _get_comp_words_by_ref) != function ]]; then
|
||||
echo _get_comp_words_by_ref: function not defined. Make sure the bash-completions system package is installed
|
||||
|
@ -23,25 +23,25 @@ _hyprctl () {
|
|||
local words cword
|
||||
_get_comp_words_by_ref -n "$COMP_WORDBREAKS" words cword
|
||||
|
||||
local -a literals=("cyclenext" "globalshortcuts" "cursorpos" "bordersize" "renameworkspace" "animationstyle" "focuswindow" "0" "auto" "swapnext" "forceallowsinput" "moveactive" "activebordercolor" "alphafullscreen" "wayland" "layers" "minsize" "monitors" "1" "kill" "settiled" "3" "focusmonitor" "swapwindow" "moveoutofgroup" "notify" "movecursor" "setcursor" "seterror" "movecurrentworkspacetomonitor" "4" "nomaxsize" "forcenoanims" "setprop" "-i" "-q" "togglefloating" "workspacerules" "movetoworkspace" "disable" "setignoregrouplock" "workspaces" "movegroupwindow" "closewindow" "0" "--instance" "binds" "movewindow" "splitratio" "alpha" "denywindowfromgroup" "workspace" "configerrors" "togglegroup" "getoption" "forceopaque" "keepaspectratio" "killactive" "pass" "decorations" "devices" "focuscurrentorlast" "submap" "global" "alphafullscreenoverride" "forcerendererreload" "movewindowpixel" "headless" "version" "dpms" "resizeactive" "moveintogroup" "5" "alphaoverride" "setfloating" "rollinglog" "::=" "rounding" "layouts" "moveworkspacetomonitor" "exec" "alphainactiveoverride" "alterzorder" "fakefullscreen" "nofocus" "keyword" "forcenoborder" "forcenodim" "--quiet" "pin" "output" "forcenoblur" "togglespecialworkspace" "fullscreen" "toggleopaque" "focusworkspaceoncurrentmonitor" "next" "changegroupactive" "-j" "instances" "execr" "exit" "clients" "all" "--batch" "dismissnotify" "inactivebordercolor" "switchxkblayout" "movetoworkspacesilent" "tagwindow" "movewindoworgroup" "-r" "movefocus" "focusurgentorlast" "remove" "activeworkspace" "dispatch" "create" "centerwindow" "2" "hyprpaper" "-1" "reload" "alphainactive" "systeminfo" "plugin" "dimaround" "activewindow" "swapactiveworkspaces" "splash" "sendshortcut" "maxsize" "lockactivegroup" "windowdancecompat" "forceopaqueoverriden" "lockgroups" "movecursortocorner" "x11" "prev" "1" "resizewindowpixel" "forcenoshadow")
|
||||
|
||||
declare -a literals=(resizeactive 2 changegroupactive -r moveintogroup forceallowsinput 4 ::= systeminfo all layouts setprop animationstyle switchxkblayout create denywindowfromgroup headless activebordercolor exec setcursor wayland focusurgentorlast workspacerules movecurrentworkspacetomonitor movetoworkspacesilent hyprpaper alpha inactivebordercolor movegroupwindow movecursortocorner movewindowpixel prev movewindow globalshortcuts clients dimaround setignoregrouplock splash execr monitors 0 forcenoborder -q animations 1 nomaxsize splitratio moveactive pass swapnext devices layers rounding lockactivegroup 5 moveworkspacetomonitor -f -i --quiet forcenodim pin 0 1 forceopaque forcenoshadow setfloating minsize alphaoverride sendshortcut workspaces cyclenext alterzorder togglegroup lockgroups bordersize dpms focuscurrentorlast -1 --batch notify remove instances 1 3 moveoutofgroup killactive 2 movetoworkspace movecursor configerrors closewindow swapwindow tagwindow forcerendererreload centerwindow auto focuswindow seterror nofocus alphafullscreen binds version -h togglespecialworkspace fullscreen windowdancecompat 0 keyword toggleopaque 3 --instance togglefloating renameworkspace alphafullscreenoverride activeworkspace x11 kill forceopaqueoverriden output global dispatch reload forcenoblur -j event --help disable -1 activewindow keepaspectratio dismissnotify focusmonitor movefocus plugin exit workspace fullscreenstate getoption alphainactiveoverride alphainactive decorations settiled config-only descriptions resizewindowpixel fakefullscreen rollinglog swapactiveworkspaces submap next movewindoworgroup cursorpos forcenoanims focusworkspaceoncurrentmonitor maxsize)
|
||||
declare -A literal_transitions
|
||||
literal_transitions[0]="([105]=1 [75]=2 [33]=3 [35]=4 [1]=2 [2]=2 [78]=2 [107]=5 [37]=2 [111]=4 [41]=2 [46]=2 [115]=2 [85]=6 [116]=8 [52]=2 [88]=4 [54]=2 [90]=9 [120]=2 [122]=2 [124]=2 [15]=2 [59]=10 [60]=2 [17]=11 [125]=12 [19]=2 [127]=2 [129]=2 [25]=13 [68]=2 [98]=4 [99]=2 [27]=2 [28]=14 [102]=2 [104]=4)"
|
||||
literal_transitions[3]="([73]=17 [13]=2 [32]=17 [55]=17 [56]=17 [91]=17 [106]=2 [123]=2 [77]=1 [16]=2 [126]=17 [3]=1 [5]=2 [64]=17 [131]=2 [133]=17 [81]=17 [134]=17 [84]=17 [31]=17 [49]=2 [12]=2 [86]=17 [10]=17 [87]=17 [141]=17)"
|
||||
literal_transitions[7]="([105]=1 [75]=2 [33]=3 [1]=2 [2]=2 [78]=2 [107]=5 [37]=2 [41]=2 [46]=2 [115]=2 [85]=6 [116]=8 [52]=2 [54]=2 [90]=9 [120]=2 [122]=2 [124]=2 [15]=2 [59]=10 [60]=2 [17]=11 [125]=12 [19]=2 [127]=2 [129]=2 [25]=13 [68]=2 [99]=2 [27]=2 [28]=14 [102]=2)"
|
||||
literal_transitions[8]="([101]=2 [130]=2 [132]=2 [0]=2 [74]=2 [36]=2 [108]=2 [109]=2 [38]=2 [110]=2 [4]=2 [79]=2 [40]=2 [80]=2 [113]=2 [6]=2 [42]=2 [43]=2 [82]=2 [83]=2 [47]=2 [48]=2 [9]=2 [50]=2 [51]=2 [53]=2 [11]=2 [112]=2 [89]=2 [118]=2 [57]=2 [92]=2 [58]=2 [93]=2 [94]=2 [61]=2 [62]=2 [128]=2 [95]=2 [63]=2 [20]=2 [97]=2 [22]=2 [23]=2 [65]=2 [66]=2 [135]=2 [136]=2 [24]=2 [26]=2 [69]=2 [100]=2 [70]=2 [140]=2 [29]=2 [71]=2)"
|
||||
literal_transitions[9]="([117]=20 [114]=16)"
|
||||
literal_transitions[11]="([103]=2)"
|
||||
literal_transitions[13]="([21]=1 [119]=1 [30]=1 [139]=1 [121]=1 [44]=1 [72]=1)"
|
||||
literal_transitions[14]="([39]=2)"
|
||||
literal_transitions[15]="([138]=2 [96]=2)"
|
||||
literal_transitions[17]="([18]=2 [7]=2)"
|
||||
literal_transitions[18]="([76]=19)"
|
||||
literal_transitions[19]="([34]=4 [45]=4)"
|
||||
literal_transitions[20]="([8]=2 [67]=2 [14]=2 [137]=2)"
|
||||
|
||||
declare -A match_anything_transitions
|
||||
match_anything_transitions=([1]=2 [0]=7 [6]=2 [15]=2 [10]=2 [5]=15 [14]=18 [7]=7 [2]=18 [16]=2 [12]=2 [11]=18)
|
||||
literal_transitions[0]="([120]=14 [43]=2 [125]=21 [81]=2 [3]=21 [51]=2 [50]=2 [128]=2 [89]=2 [58]=21 [8]=2 [10]=2 [11]=3 [130]=4 [13]=5 [97]=6 [101]=2 [102]=21 [133]=7 [100]=2 [137]=2 [22]=2 [19]=2 [140]=8 [25]=2 [143]=2 [107]=9 [146]=10 [69]=2 [33]=2 [34]=2 [78]=21 [114]=2 [37]=2 [151]=2 [116]=2 [121]=13 [123]=21 [39]=11 [42]=21 [79]=15 [118]=12)"
|
||||
literal_transitions[1]="([81]=2 [51]=2 [50]=2 [128]=2 [8]=2 [89]=2 [10]=2 [11]=3 [130]=4 [13]=5 [97]=6 [101]=2 [133]=7 [100]=2 [22]=2 [19]=2 [137]=2 [140]=8 [25]=2 [143]=2 [107]=9 [146]=10 [69]=2 [33]=2 [34]=2 [114]=2 [37]=2 [151]=2 [116]=2 [39]=11 [118]=12 [121]=13 [120]=14 [79]=15 [43]=2)"
|
||||
literal_transitions[3]="([139]=2 [63]=16 [64]=16 [45]=16 [105]=16 [27]=2 [26]=2 [52]=4 [5]=16 [66]=2 [67]=16 [129]=16 [113]=16 [12]=2 [74]=4 [99]=2 [35]=16 [152]=16 [98]=16 [59]=16 [117]=16 [41]=16 [17]=2 [138]=16 [154]=2 [122]=16)"
|
||||
literal_transitions[6]="([126]=2)"
|
||||
literal_transitions[10]="([56]=2)"
|
||||
literal_transitions[11]="([9]=2)"
|
||||
literal_transitions[12]="([14]=19 [80]=22)"
|
||||
literal_transitions[13]="([142]=2)"
|
||||
literal_transitions[14]="([0]=2 [84]=2 [2]=2 [85]=2 [4]=2 [87]=2 [88]=2 [90]=2 [91]=2 [92]=2 [93]=2 [94]=2 [96]=2 [15]=2 [18]=2 [103]=2 [21]=2 [104]=2 [23]=2 [24]=2 [28]=2 [29]=2 [30]=2 [108]=2 [111]=2 [32]=2 [112]=2 [36]=2 [38]=2 [119]=2 [124]=2 [46]=2 [47]=2 [48]=2 [49]=2 [53]=2 [55]=2 [131]=2 [132]=2 [134]=2 [135]=2 [60]=2 [136]=20 [141]=2 [65]=2 [144]=2 [145]=2 [68]=2 [147]=2 [70]=2 [71]=2 [72]=2 [73]=2 [148]=2 [75]=2 [76]=2 [150]=2 [153]=2)"
|
||||
literal_transitions[15]="([86]=4 [6]=4 [109]=4 [61]=4 [77]=4 [54]=4 [62]=4)"
|
||||
literal_transitions[16]="([40]=2 [44]=2)"
|
||||
literal_transitions[17]="([7]=23)"
|
||||
literal_transitions[18]="([31]=2 [149]=2)"
|
||||
literal_transitions[19]="([95]=2 [16]=2 [115]=2 [20]=2)"
|
||||
literal_transitions[20]="([106]=2 [82]=2 [127]=2 [1]=2 [83]=2)"
|
||||
literal_transitions[23]="([57]=21 [110]=21)"
|
||||
declare -A match_anything_transitions=([6]=17 [7]=2 [0]=1 [22]=2 [5]=18 [4]=2 [2]=17 [18]=2 [11]=17 [8]=2 [9]=2 [13]=17 [10]=17 [1]=1)
|
||||
declare -A subword_transitions
|
||||
|
||||
local state=0
|
||||
|
@ -79,21 +79,9 @@ _hyprctl () {
|
|||
done
|
||||
|
||||
|
||||
local -a matches=()
|
||||
|
||||
local prefix="${words[$cword]}"
|
||||
|
||||
local shortest_suffix="$word"
|
||||
for ((i=0; i < ${#COMP_WORDBREAKS}; i++)); do
|
||||
local char="${COMP_WORDBREAKS:$i:1}"
|
||||
local candidate="${word##*$char}"
|
||||
if [[ ${#candidate} -lt ${#shortest_suffix} ]]; then
|
||||
shortest_suffix=$candidate
|
||||
fi
|
||||
done
|
||||
local superfluous_prefix=""
|
||||
if [[ "$shortest_suffix" != "$word" ]]; then
|
||||
local superfluous_prefix=${word%$shortest_suffix}
|
||||
fi
|
||||
|
||||
if [[ -v "literal_transitions[$state]" ]]; then
|
||||
local state_transitions_initializer=${literal_transitions[$state]}
|
||||
declare -A state_transitions
|
||||
|
@ -102,25 +90,38 @@ _hyprctl () {
|
|||
for literal_id in "${!state_transitions[@]}"; do
|
||||
local literal="${literals[$literal_id]}"
|
||||
if [[ $literal = "${prefix}"* ]]; then
|
||||
local completion=${literal#"$superfluous_prefix"}
|
||||
COMPREPLY+=("$completion ")
|
||||
matches+=("$literal ")
|
||||
fi
|
||||
done
|
||||
fi
|
||||
declare -A commands
|
||||
commands=([5]=1 [16]=2 [12]=3 [10]=0)
|
||||
commands=([7]=0 [22]=1 [8]=3 [5]=2)
|
||||
if [[ -v "commands[$state]" ]]; then
|
||||
local command_id=${commands[$state]}
|
||||
local completions=()
|
||||
mapfile -t completions < <(_hyprctl_cmd_${command_id} "$prefix" | cut -f1)
|
||||
readarray -t completions < <(_hyprctl_cmd_${command_id} "$prefix" | cut -f1)
|
||||
for item in "${completions[@]}"; do
|
||||
if [[ $item = "${prefix}"* ]]; then
|
||||
COMPREPLY+=("$item")
|
||||
matches+=("$item")
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
|
||||
local shortest_suffix="$prefix"
|
||||
for ((i=0; i < ${#COMP_WORDBREAKS}; i++)); do
|
||||
local char="${COMP_WORDBREAKS:$i:1}"
|
||||
local candidate=${prefix##*$char}
|
||||
if [[ ${#candidate} -lt ${#shortest_suffix} ]]; then
|
||||
shortest_suffix=$candidate
|
||||
fi
|
||||
done
|
||||
local superfluous_prefix=""
|
||||
if [[ "$shortest_suffix" != "$prefix" ]]; then
|
||||
local superfluous_prefix=${prefix%$shortest_suffix}
|
||||
fi
|
||||
COMPREPLY=("${matches[@]#$superfluous_prefix}")
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
|
|
|
@ -1,21 +1,21 @@
|
|||
function _hyprctl_3
|
||||
function _hyprctl_2
|
||||
set 1 $argv[1]
|
||||
hyprctl monitors | awk '/Monitor/{ print $2 }'
|
||||
end
|
||||
|
||||
function _hyprctl_4
|
||||
set 1 $argv[1]
|
||||
hyprpm list | awk '/Plugin/{ print $4 }'
|
||||
hyprctl clients | awk '/class/{print $2}'
|
||||
end
|
||||
|
||||
function _hyprctl_3
|
||||
set 1 $argv[1]
|
||||
hyprctl devices | sed -n '/Keyboard at/{n; s/^\s\+//; p}'
|
||||
end
|
||||
|
||||
function _hyprctl_1
|
||||
set 1 $argv[1]
|
||||
hyprctl clients | awk '/class/{ print $2 }'
|
||||
end
|
||||
|
||||
function _hyprctl_2
|
||||
set 1 $argv[1]
|
||||
hyprctl devices | sed -n '/Keyboard at/{n; s/^\s\+//; p}'
|
||||
hyprpm list | awk '/Plugin/{print $4}'
|
||||
end
|
||||
|
||||
function _hyprctl
|
||||
|
@ -29,145 +29,160 @@ function _hyprctl
|
|||
set COMP_CWORD (count $COMP_WORDS)
|
||||
end
|
||||
|
||||
set --local literals "cyclenext" "globalshortcuts" "cursorpos" "bordersize" "renameworkspace" "animationstyle" "focuswindow" "0" "auto" "swapnext" "forceallowsinput" "moveactive" "activebordercolor" "alphafullscreen" "wayland" "layers" "minsize" "monitors" "1" "kill" "settiled" "3" "focusmonitor" "swapwindow" "moveoutofgroup" "notify" "movecursor" "setcursor" "seterror" "movecurrentworkspacetomonitor" "4" "nomaxsize" "forcenoanims" "setprop" "-i" "-q" "togglefloating" "workspacerules" "movetoworkspace" "disable" "setignoregrouplock" "workspaces" "movegroupwindow" "closewindow" "0" "--instance" "binds" "movewindow" "splitratio" "alpha" "denywindowfromgroup" "workspace" "configerrors" "togglegroup" "getoption" "forceopaque" "keepaspectratio" "killactive" "pass" "decorations" "devices" "focuscurrentorlast" "submap" "global" "alphafullscreenoverride" "forcerendererreload" "movewindowpixel" "headless" "version" "dpms" "resizeactive" "moveintogroup" "5" "alphaoverride" "setfloating" "rollinglog" "::=" "rounding" "layouts" "moveworkspacetomonitor" "exec" "alphainactiveoverride" "alterzorder" "fakefullscreen" "nofocus" "keyword" "forcenoborder" "forcenodim" "--quiet" "pin" "output" "forcenoblur" "togglespecialworkspace" "fullscreen" "toggleopaque" "focusworkspaceoncurrentmonitor" "next" "changegroupactive" "-j" "instances" "execr" "exit" "clients" "all" "--batch" "dismissnotify" "inactivebordercolor" "switchxkblayout" "movetoworkspacesilent" "tagwindow" "movewindoworgroup" "-r" "movefocus" "focusurgentorlast" "remove" "activeworkspace" "dispatch" "create" "centerwindow" "2" "hyprpaper" "-1" "reload" "alphainactive" "systeminfo" "plugin" "dimaround" "activewindow" "swapactiveworkspaces" "splash" "sendshortcut" "maxsize" "lockactivegroup" "windowdancecompat" "forceopaqueoverriden" "lockgroups" "movecursortocorner" "x11" "prev" "1" "resizewindowpixel" "forcenoshadow"
|
||||
set literals "resizeactive" "2" "changegroupactive" "-r" "moveintogroup" "forceallowsinput" "4" "::=" "systeminfo" "all" "layouts" "setprop" "animationstyle" "switchxkblayout" "create" "denywindowfromgroup" "headless" "activebordercolor" "exec" "setcursor" "wayland" "focusurgentorlast" "workspacerules" "movecurrentworkspacetomonitor" "movetoworkspacesilent" "hyprpaper" "alpha" "inactivebordercolor" "movegroupwindow" "movecursortocorner" "movewindowpixel" "prev" "movewindow" "globalshortcuts" "clients" "dimaround" "setignoregrouplock" "splash" "execr" "monitors" "0" "forcenoborder" "-q" "animations" "1" "nomaxsize" "splitratio" "moveactive" "pass" "swapnext" "devices" "layers" "rounding" "lockactivegroup" "5" "moveworkspacetomonitor" "-f" "-i" "--quiet" "forcenodim" "pin" "0" "1" "forceopaque" "forcenoshadow" "setfloating" "minsize" "alphaoverride" "sendshortcut" "workspaces" "cyclenext" "alterzorder" "togglegroup" "lockgroups" "bordersize" "dpms" "focuscurrentorlast" "-1" "--batch" "notify" "remove" "instances" "1" "3" "moveoutofgroup" "killactive" "2" "movetoworkspace" "movecursor" "configerrors" "closewindow" "swapwindow" "tagwindow" "forcerendererreload" "centerwindow" "auto" "focuswindow" "seterror" "nofocus" "alphafullscreen" "binds" "version" "-h" "togglespecialworkspace" "fullscreen" "windowdancecompat" "0" "keyword" "toggleopaque" "3" "--instance" "togglefloating" "renameworkspace" "alphafullscreenoverride" "activeworkspace" "x11" "kill" "forceopaqueoverriden" "output" "global" "dispatch" "reload" "forcenoblur" "-j" "event" "--help" "disable" "-1" "activewindow" "keepaspectratio" "dismissnotify" "focusmonitor" "movefocus" "plugin" "exit" "workspace" "fullscreenstate" "getoption" "alphainactiveoverride" "alphainactive" "decorations" "settiled" "config-only" "descriptions" "resizewindowpixel" "fakefullscreen" "rollinglog" "swapactiveworkspaces" "submap" "next" "movewindoworgroup" "cursorpos" "forcenoanims" "focusworkspaceoncurrentmonitor" "maxsize"
|
||||
|
||||
set --local descriptions
|
||||
set descriptions[1] "Focus the next window on a workspace"
|
||||
set descriptions[3] "Get the current cursor pos in global layout coordinates"
|
||||
set descriptions[5] "Rename a workspace"
|
||||
set descriptions[7] "Focus the first window matching"
|
||||
set descriptions[10] "Swap the focused window with the next window"
|
||||
set descriptions[12] "Move the active window"
|
||||
set descriptions[16] "List the layers"
|
||||
set descriptions[18] "List active outputs with their properties"
|
||||
set descriptions[20] "Get into a kill mode, where you can kill an app by clicking on it"
|
||||
set descriptions[21] "Set the current window's floating state to false"
|
||||
set descriptions[22] "ERROR"
|
||||
set descriptions[23] "Focus a monitor"
|
||||
set descriptions[24] "Swap the active window with another window"
|
||||
set descriptions[25] "Move the active window out of a group"
|
||||
set descriptions[26] "Send a notification using the built-in Hyprland notification system"
|
||||
set descriptions[27] "Move the cursor to a specified position"
|
||||
set descriptions[28] "Set the cursor theme and reloads the cursor manager"
|
||||
set descriptions[29] "Set the hyprctl error string"
|
||||
set descriptions[30] "Move the active workspace to a monitor"
|
||||
set descriptions[31] "CONFUSED"
|
||||
set descriptions[34] "Set a property of a window"
|
||||
set descriptions[35] "Specify the Hyprland instance"
|
||||
set descriptions[36] "Disable output"
|
||||
set descriptions[37] "Toggle the current window's floating state"
|
||||
set descriptions[38] "Get the list of defined workspace rules"
|
||||
set descriptions[39] "Move the focused window to a workspace"
|
||||
set descriptions[41] "Temporarily enable or disable binds:ignore_group_lock"
|
||||
set descriptions[42] "List all workspaces with their properties"
|
||||
set descriptions[43] "Swap the active window with the next or previous in a group"
|
||||
set descriptions[44] "Close a specified window"
|
||||
set descriptions[45] "WARNING"
|
||||
set descriptions[46] "Specify the Hyprland instance"
|
||||
set descriptions[47] "List all registered binds"
|
||||
set descriptions[48] "Move the active window in a direction or to a monitor"
|
||||
set descriptions[49] "Change the split ratio"
|
||||
set descriptions[51] "Prohibit the active window from becoming or being inserted into group"
|
||||
set descriptions[52] "Change the workspace"
|
||||
set descriptions[53] "List all current config parsing errors"
|
||||
set descriptions[54] "Toggle the current active window into a group"
|
||||
set descriptions[55] "Get the config option status (values)"
|
||||
set descriptions[58] "Close the active window"
|
||||
set descriptions[59] "Pass the key to a specified window"
|
||||
set descriptions[60] "List all decorations and their info"
|
||||
set descriptions[61] "List all connected keyboards and mice"
|
||||
set descriptions[62] "Switch focus from current to previously focused window"
|
||||
set descriptions[63] "Change the current mapping group"
|
||||
set descriptions[64] "Execute a Global Shortcut using the GlobalShortcuts portal"
|
||||
set descriptions[66] "Force the renderer to reload all resources and outputs"
|
||||
set descriptions[67] "Move a selected window"
|
||||
set descriptions[69] "Print the Hyprland version: flags, commit and branch of build"
|
||||
set descriptions[70] "Set all monitors' DPMS status"
|
||||
set descriptions[71] "Resize the active window"
|
||||
set descriptions[72] "Move the active window into a group"
|
||||
set descriptions[73] "OK"
|
||||
set descriptions[75] "Set the current window's floating state to true"
|
||||
set descriptions[76] "Print tail of the log"
|
||||
set descriptions[79] "List all layouts available (including plugin ones)"
|
||||
set descriptions[80] "Move a workspace to a monitor"
|
||||
set descriptions[81] "Execute a shell command"
|
||||
set descriptions[83] "Modify the window stack order of the active or specified window"
|
||||
set descriptions[84] "Toggle the focused window's internal fullscreen state"
|
||||
set descriptions[86] "Issue a keyword to call a config keyword dynamically"
|
||||
set descriptions[89] "Disable output"
|
||||
set descriptions[90] "Pin a window"
|
||||
set descriptions[91] "Allows adding/removing fake outputs to a specific backend"
|
||||
set descriptions[93] "Toggle a special workspace on/off"
|
||||
set descriptions[94] "Toggle the focused window's fullscreen state"
|
||||
set descriptions[95] "Toggle the current window to always be opaque"
|
||||
set descriptions[96] "Focus the requested workspace"
|
||||
set descriptions[98] "Switch to the next window in a group"
|
||||
set descriptions[99] "Output in JSON format"
|
||||
set descriptions[100] "List all running Hyprland instances and their info"
|
||||
set descriptions[101] "Execute a raw shell command"
|
||||
set descriptions[102] "Exit the compositor with no questions asked"
|
||||
set descriptions[103] "List all windows with their properties"
|
||||
set descriptions[105] "Execute a batch of commands separated by ;"
|
||||
set descriptions[106] "Dismiss all or up to amount of notifications"
|
||||
set descriptions[108] "Set the xkb layout index for a keyboard"
|
||||
set descriptions[109] "Move window doesnt switch to the workspace"
|
||||
set descriptions[110] "Apply a tag to the window"
|
||||
set descriptions[111] "Behave as moveintogroup"
|
||||
set descriptions[112] "Refresh state after issuing the command"
|
||||
set descriptions[113] "Move the focus in a direction"
|
||||
set descriptions[114] "Focus the urgent window or the last window"
|
||||
set descriptions[116] "Get the active workspace name and its properties"
|
||||
set descriptions[117] "Issue a dispatch to call a keybind dispatcher with an arg"
|
||||
set descriptions[119] "Center the active window"
|
||||
set descriptions[120] "HINT"
|
||||
set descriptions[121] "Interact with hyprpaper if present"
|
||||
set descriptions[122] "No Icon"
|
||||
set descriptions[123] "Force reload the config"
|
||||
set descriptions[125] "Print system info"
|
||||
set descriptions[126] "Interact with a plugin"
|
||||
set descriptions[128] "Get the active window name and its properties"
|
||||
set descriptions[129] "Swap the active workspaces between two monitors"
|
||||
set descriptions[130] "Print the current random splash"
|
||||
set descriptions[131] "On shortcut X sends shortcut Y to a specified window"
|
||||
set descriptions[133] "Lock the focused group"
|
||||
set descriptions[136] "Lock the groups"
|
||||
set descriptions[137] "Move the cursor to the corner of the active window"
|
||||
set descriptions[140] "INFO"
|
||||
set descriptions[141] "Resize a selected window"
|
||||
set descriptions
|
||||
set descriptions[1] "Resize the active window"
|
||||
set descriptions[2] "Fullscreen"
|
||||
set descriptions[3] "Switch to the next window in a group"
|
||||
set descriptions[4] "Refresh state after issuing the command"
|
||||
set descriptions[5] "Move the active window into a group"
|
||||
set descriptions[7] "CONFUSED"
|
||||
set descriptions[9] "Print system info"
|
||||
set descriptions[11] "List all layouts available (including plugin ones)"
|
||||
set descriptions[12] "Set a property of a window"
|
||||
set descriptions[14] "Set the xkb layout index for a keyboard"
|
||||
set descriptions[16] "Prohibit the active window from becoming or being inserted into group"
|
||||
set descriptions[19] "Execute a shell command"
|
||||
set descriptions[20] "Set the cursor theme and reloads the cursor manager"
|
||||
set descriptions[22] "Focus the urgent window or the last window"
|
||||
set descriptions[23] "Get the list of defined workspace rules"
|
||||
set descriptions[24] "Move the active workspace to a monitor"
|
||||
set descriptions[25] "Move window doesnt switch to the workspace"
|
||||
set descriptions[26] "Interact with hyprpaper if present"
|
||||
set descriptions[29] "Swap the active window with the next or previous in a group"
|
||||
set descriptions[30] "Move the cursor to the corner of the active window"
|
||||
set descriptions[31] "Move a selected window"
|
||||
set descriptions[33] "Move the active window in a direction or to a monitor"
|
||||
set descriptions[34] "Lists all global shortcuts"
|
||||
set descriptions[35] "List all windows with their properties"
|
||||
set descriptions[37] "Temporarily enable or disable binds:ignore_group_lock"
|
||||
set descriptions[38] "Print the current random splash"
|
||||
set descriptions[39] "Execute a raw shell command"
|
||||
set descriptions[40] "List active outputs with their properties"
|
||||
set descriptions[43] "Disable output"
|
||||
set descriptions[44] "Gets the current config info about animations and beziers"
|
||||
set descriptions[47] "Change the split ratio"
|
||||
set descriptions[48] "Move the active window"
|
||||
set descriptions[49] "Pass the key to a specified window"
|
||||
set descriptions[50] "Swap the focused window with the next window"
|
||||
set descriptions[51] "List all connected keyboards and mice"
|
||||
set descriptions[52] "List the layers"
|
||||
set descriptions[54] "Lock the focused group"
|
||||
set descriptions[55] "OK"
|
||||
set descriptions[56] "Move a workspace to a monitor"
|
||||
set descriptions[58] "Specify the Hyprland instance"
|
||||
set descriptions[59] "Disable output"
|
||||
set descriptions[61] "Pin a window"
|
||||
set descriptions[62] "WARNING"
|
||||
set descriptions[63] "INFO"
|
||||
set descriptions[66] "Set the current window's floating state to true"
|
||||
set descriptions[69] "On shortcut X sends shortcut Y to a specified window"
|
||||
set descriptions[70] "List all workspaces with their properties"
|
||||
set descriptions[71] "Focus the next window on a workspace"
|
||||
set descriptions[72] "Modify the window stack order of the active or specified window"
|
||||
set descriptions[73] "Toggle the current active window into a group"
|
||||
set descriptions[74] "Lock the groups"
|
||||
set descriptions[76] "Set all monitors' DPMS status"
|
||||
set descriptions[77] "Switch focus from current to previously focused window"
|
||||
set descriptions[78] "No Icon"
|
||||
set descriptions[79] "Execute a batch of commands separated by ;"
|
||||
set descriptions[80] "Send a notification using the built-in Hyprland notification system"
|
||||
set descriptions[82] "List all running Hyprland instances and their info"
|
||||
set descriptions[83] "Maximize no fullscreen"
|
||||
set descriptions[84] "Maximize and fullscreen"
|
||||
set descriptions[85] "Move the active window out of a group"
|
||||
set descriptions[86] "Close the active window"
|
||||
set descriptions[87] "HINT"
|
||||
set descriptions[88] "Move the focused window to a workspace"
|
||||
set descriptions[89] "Move the cursor to a specified position"
|
||||
set descriptions[90] "List all current config parsing errors"
|
||||
set descriptions[91] "Close a specified window"
|
||||
set descriptions[92] "Swap the active window with another window"
|
||||
set descriptions[93] "Apply a tag to the window"
|
||||
set descriptions[94] "Force the renderer to reload all resources and outputs"
|
||||
set descriptions[95] "Center the active window"
|
||||
set descriptions[97] "Focus the first window matching"
|
||||
set descriptions[98] "Set the hyprctl error string"
|
||||
set descriptions[101] "List all registered binds"
|
||||
set descriptions[102] "Print the Hyprland version: flags, commit and branch of build"
|
||||
set descriptions[103] "Prints the help message"
|
||||
set descriptions[104] "Toggle a special workspace on/off"
|
||||
set descriptions[105] "Toggle the focused window's fullscreen state"
|
||||
set descriptions[107] "None"
|
||||
set descriptions[108] "Issue a keyword to call a config keyword dynamically"
|
||||
set descriptions[109] "Toggle the current window to always be opaque"
|
||||
set descriptions[110] "ERROR"
|
||||
set descriptions[111] "Specify the Hyprland instance"
|
||||
set descriptions[112] "Toggle the current window's floating state"
|
||||
set descriptions[113] "Rename a workspace"
|
||||
set descriptions[115] "Get the active workspace name and its properties"
|
||||
set descriptions[117] "Get into a kill mode, where you can kill an app by clicking on it"
|
||||
set descriptions[119] "Allows adding/removing fake outputs to a specific backend"
|
||||
set descriptions[120] "Execute a Global Shortcut using the GlobalShortcuts portal"
|
||||
set descriptions[121] "Issue a dispatch to call a keybind dispatcher with an arg"
|
||||
set descriptions[122] "Force reload the config"
|
||||
set descriptions[124] "Output in JSON format"
|
||||
set descriptions[125] "Emits a custom event to socket2"
|
||||
set descriptions[126] "Prints the help message"
|
||||
set descriptions[128] "Current"
|
||||
set descriptions[129] "Get the active window name and its properties"
|
||||
set descriptions[131] "Dismiss all or up to amount of notifications"
|
||||
set descriptions[132] "Focus a monitor"
|
||||
set descriptions[133] "Move the focus in a direction"
|
||||
set descriptions[134] "Interact with a plugin"
|
||||
set descriptions[135] "Exit the compositor with no questions asked"
|
||||
set descriptions[136] "Change the workspace"
|
||||
set descriptions[137] "Sets the focused window’s fullscreen mode and the one sent to the client"
|
||||
set descriptions[138] "Get the config option status (values)"
|
||||
set descriptions[141] "List all decorations and their info"
|
||||
set descriptions[142] "Set the current window's floating state to false"
|
||||
set descriptions[144] "Return a parsable JSON with all the config options, descriptions, value types and ranges"
|
||||
set descriptions[145] "Resize a selected window"
|
||||
set descriptions[146] "Toggle the focused window's internal fullscreen state"
|
||||
set descriptions[147] "Print tail of the log"
|
||||
set descriptions[148] "Swap the active workspaces between two monitors"
|
||||
set descriptions[149] "Change the current mapping group"
|
||||
set descriptions[151] "Behave as moveintogroup"
|
||||
set descriptions[152] "Get the current cursor pos in global layout coordinates"
|
||||
set descriptions[154] "Focus the requested workspace"
|
||||
|
||||
set --local literal_transitions
|
||||
set literal_transitions[1] "set inputs 106 76 34 36 2 3 79 108 38 112 42 47 116 86 117 53 89 55 91 121 123 125 16 60 61 18 126 20 128 130 26 69 99 100 28 29 103 105; set tos 2 3 4 5 3 3 3 6 3 5 3 3 3 7 9 3 5 3 10 3 3 3 3 11 3 12 13 3 3 3 14 3 5 3 3 15 3 5"
|
||||
set literal_transitions[4] "set inputs 74 14 33 56 57 92 107 124 78 17 127 4 6 65 132 134 82 135 85 32 50 13 87 11 88 142; set tos 18 3 18 18 18 18 3 3 2 3 18 2 3 18 3 18 18 18 18 18 3 3 18 18 18 18"
|
||||
set literal_transitions[8] "set inputs 106 76 34 2 3 79 108 38 42 47 116 86 117 53 55 91 121 123 125 16 60 61 18 126 20 128 130 26 69 100 28 29 103; set tos 2 3 4 3 3 3 6 3 3 3 3 7 9 3 3 10 3 3 3 3 11 3 12 13 3 3 3 14 3 3 3 15 3"
|
||||
set literal_transitions[9] "set inputs 102 131 133 1 75 37 109 110 39 111 5 80 41 81 114 7 43 44 83 84 48 49 10 51 52 54 12 113 90 119 58 93 59 94 95 62 63 129 96 64 21 98 23 24 66 67 136 137 25 27 70 101 71 141 30 72; set tos 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3"
|
||||
set literal_transitions[10] "set inputs 118 115; set tos 21 17"
|
||||
set literal_transitions[12] "set inputs 104; set tos 3"
|
||||
set literal_transitions[14] "set inputs 22 120 31 140 122 45 73; set tos 2 2 2 2 2 2 2"
|
||||
set literal_transitions[15] "set inputs 40; set tos 3"
|
||||
set literal_transitions[16] "set inputs 139 97; set tos 3 3"
|
||||
set literal_transitions[18] "set inputs 19 8; set tos 3 3"
|
||||
set literal_transitions[19] "set inputs 77; set tos 20"
|
||||
set literal_transitions[20] "set inputs 35 46; set tos 5 5"
|
||||
set literal_transitions[21] "set inputs 9 68 15 138; set tos 3 3 3 3"
|
||||
set literal_transitions
|
||||
set literal_transitions[1] "set inputs 121 44 126 82 4 52 51 129 90 59 9 11 12 131 14 98 102 103 134 101 138 23 20 141 26 144 108 147 70 34 35 79 115 38 152 117 122 124 40 43 80 119; set tos 15 3 22 3 22 3 3 3 3 22 3 3 4 5 6 7 3 22 8 3 3 3 3 9 3 3 10 11 3 3 3 22 3 3 3 3 14 22 12 22 16 13"
|
||||
set literal_transitions[2] "set inputs 82 52 51 129 9 90 11 12 131 14 98 102 134 101 23 20 138 141 26 144 108 147 70 34 35 115 38 152 117 40 119 122 121 80 44; set tos 3 3 3 3 3 3 3 4 5 6 7 3 8 3 3 3 3 9 3 3 10 11 3 3 3 3 3 3 3 12 13 14 15 16 3"
|
||||
set literal_transitions[4] "set inputs 140 64 65 46 106 28 27 53 6 67 68 130 114 13 75 100 36 153 99 60 118 42 18 139 155 123; set tos 3 17 17 17 17 3 3 5 17 3 17 17 17 3 5 3 17 17 17 17 17 17 3 17 3 17"
|
||||
set literal_transitions[7] "set inputs 127; set tos 3"
|
||||
set literal_transitions[11] "set inputs 57; set tos 3"
|
||||
set literal_transitions[12] "set inputs 10; set tos 3"
|
||||
set literal_transitions[13] "set inputs 15 81; set tos 20 23"
|
||||
set literal_transitions[14] "set inputs 143; set tos 3"
|
||||
set literal_transitions[15] "set inputs 1 85 3 86 5 88 89 91 92 93 94 95 97 16 19 104 22 105 24 25 29 30 31 109 112 33 113 37 39 120 125 47 48 49 50 54 56 132 133 135 136 61 137 142 66 145 146 69 148 71 72 73 74 149 76 77 151 154; set tos 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 21 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3"
|
||||
set literal_transitions[16] "set inputs 87 7 110 62 78 55 63; set tos 5 5 5 5 5 5 5"
|
||||
set literal_transitions[17] "set inputs 41 45; set tos 3 3"
|
||||
set literal_transitions[18] "set inputs 8; set tos 24"
|
||||
set literal_transitions[19] "set inputs 32 150; set tos 3 3"
|
||||
set literal_transitions[20] "set inputs 96 17 116 21; set tos 3 3 3 3"
|
||||
set literal_transitions[21] "set inputs 107 83 128 2 84; set tos 3 3 3 3 3"
|
||||
set literal_transitions[24] "set inputs 58 111; set tos 22 22"
|
||||
|
||||
set --local match_anything_transitions_from 2 1 7 16 11 6 15 8 3 17 13 12
|
||||
set --local match_anything_transitions_to 3 8 3 3 3 16 19 8 19 3 3 19
|
||||
set match_anything_transitions_from 7 8 1 23 6 5 3 19 12 9 10 14 11 2
|
||||
set match_anything_transitions_to 18 3 2 3 19 3 18 3 18 3 3 18 18 2
|
||||
|
||||
set --local state 1
|
||||
set --local word_index 2
|
||||
set state 1
|
||||
set word_index 2
|
||||
while test $word_index -lt $COMP_CWORD
|
||||
set --local -- word $COMP_WORDS[$word_index]
|
||||
set -- word $COMP_WORDS[$word_index]
|
||||
|
||||
if set --query literal_transitions[$state] && test -n $literal_transitions[$state]
|
||||
set --local --erase inputs
|
||||
set --local --erase tos
|
||||
set --erase inputs
|
||||
set --erase tos
|
||||
eval $literal_transitions[$state]
|
||||
|
||||
if contains -- $word $literals
|
||||
set --local literal_matched 0
|
||||
set literal_matched 0
|
||||
for literal_id in (seq 1 (count $literals))
|
||||
if test $literals[$literal_id] = $word
|
||||
set --local index (contains --index -- $literal_id $inputs)
|
||||
set index (contains --index -- $literal_id $inputs)
|
||||
set state $tos[$index]
|
||||
set word_index (math $word_index + 1)
|
||||
set literal_matched 1
|
||||
|
@ -181,7 +196,7 @@ function _hyprctl
|
|||
end
|
||||
|
||||
if set --query match_anything_transitions_from[$state] && test -n $match_anything_transitions_from[$state]
|
||||
set --local index (contains --index -- $state $match_anything_transitions_from)
|
||||
set index (contains --index -- $state $match_anything_transitions_from)
|
||||
set state $match_anything_transitions_to[$index]
|
||||
set word_index (math $word_index + 1)
|
||||
continue
|
||||
|
@ -191,8 +206,8 @@ function _hyprctl
|
|||
end
|
||||
|
||||
if set --query literal_transitions[$state] && test -n $literal_transitions[$state]
|
||||
set --local --erase inputs
|
||||
set --local --erase tos
|
||||
set --erase inputs
|
||||
set --erase tos
|
||||
eval $literal_transitions[$state]
|
||||
for literal_id in $inputs
|
||||
if test -n $descriptions[$literal_id]
|
||||
|
@ -203,14 +218,14 @@ function _hyprctl
|
|||
end
|
||||
end
|
||||
|
||||
set command_states 6 17 13 11
|
||||
set command_ids 2 3 4 1
|
||||
set command_states 8 23 9 6
|
||||
set command_ids 1 2 4 3
|
||||
if contains $state $command_states
|
||||
set --local index (contains --index $state $command_states)
|
||||
set --local function_id $command_ids[$index]
|
||||
set --local function_name _hyprctl_$function_id
|
||||
set --local --erase inputs
|
||||
set --local --erase tos
|
||||
set index (contains --index $state $command_states)
|
||||
set function_id $command_ids[$index]
|
||||
set function_name _hyprctl_$function_id
|
||||
set --erase inputs
|
||||
set --erase tos
|
||||
$function_name "$COMP_WORDS[$COMP_CWORD]"
|
||||
end
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ hyprctl [<OPTIONS>]... <ARGUMENTS>
|
|||
| (-r) "Refresh state after issuing the command"
|
||||
| (--batch) "Execute a batch of commands separated by ;"
|
||||
| (-q | --quiet) "Disable output"
|
||||
| (-h | --help) "Prints the help message"
|
||||
;
|
||||
|
||||
<WINDOWS> ::= {{{ hyprctl clients | awk '/class/{print $2}' }}};
|
||||
|
@ -59,16 +60,18 @@ hyprctl [<OPTIONS>]... <ARGUMENTS>
|
|||
|
||||
<ARGUMENTS> ::= (activewindow) "Get the active window name and its properties"
|
||||
| (activeworkspace) "Get the active workspace name and its properties"
|
||||
| (animations) "Gets the current config info about animations and beziers"
|
||||
| (binds) "List all registered binds"
|
||||
| (clients) "List all windows with their properties"
|
||||
| (configerrors) "List all current config parsing errors"
|
||||
| (cursorpos) "Get the current cursor pos in global layout coordinates"
|
||||
| (decorations <WINDOWS>) "List all decorations and their info"
|
||||
| (descriptions) "Return a parsable JSON with all the config options, descriptions, value types and ranges"
|
||||
| (devices) "List all connected keyboards and mice"
|
||||
| (dismissnotify <NUM>) "Dismiss all or up to amount of notifications"
|
||||
| (dispatch <DISPATCHERS>) "Issue a dispatch to call a keybind dispatcher with an arg"
|
||||
| (getoption) "Get the config option status (values)"
|
||||
| (globalshortcuts) ""
|
||||
| (globalshortcuts) "Lists all global shortcuts"
|
||||
| (hyprpaper) "Interact with hyprpaper if present"
|
||||
| (instances) "List all running Hyprland instances and their info"
|
||||
| (keyword <KEYWORDS>) "Issue a keyword to call a config keyword dynamically"
|
||||
|
@ -79,8 +82,8 @@ hyprctl [<OPTIONS>]... <ARGUMENTS>
|
|||
| (notify <NOTIFICATION_TYPES> <NUM>) "Send a notification using the built-in Hyprland notification system"
|
||||
| (output (create (wayland | x11 | headless | auto) | remove <MONITORS>)) "Allows adding/removing fake outputs to a specific backend"
|
||||
| (plugin <AVAILABLE_PLUGINS>) "Interact with a plugin"
|
||||
| (reload) "Force reload the config"
|
||||
| (rollinglog) "Print tail of the log"
|
||||
| (reload [config-only]) "Force reload the config"
|
||||
| (rollinglog [-f]) "Print tail of the log"
|
||||
| (setcursor) "Set the cursor theme and reloads the cursor manager"
|
||||
| (seterror [disable]) "Set the hyprctl error string"
|
||||
| (setprop <PROPS>) "Set a property of a window"
|
||||
|
@ -92,6 +95,13 @@ hyprctl [<OPTIONS>]... <ARGUMENTS>
|
|||
| (workspaces) "List all workspaces with their properties"
|
||||
;
|
||||
|
||||
<WINDOW_STATE> ::= (-1) "Current"
|
||||
| (0) "None"
|
||||
| (1) "Maximize no fullscreen"
|
||||
| (2) "Fullscreen"
|
||||
| (3) "Maximize and fullscreen"
|
||||
;
|
||||
|
||||
<DISPATCHERS> ::= (exec) "Execute a shell command"
|
||||
| (execr) "Execute a raw shell command"
|
||||
| (pass) "Pass the key to a specified window"
|
||||
|
@ -106,6 +116,7 @@ hyprctl [<OPTIONS>]... <ARGUMENTS>
|
|||
| (settiled) "Set the current window's floating state to false"
|
||||
| (fullscreen) "Toggle the focused window's fullscreen state"
|
||||
| (fakefullscreen) "Toggle the focused window's internal fullscreen state"
|
||||
| (fullscreenstate <WINDOW_STATE>) "Sets the focused window’s fullscreen mode and the one sent to the client"
|
||||
| (dpms) "Set all monitors' DPMS status"
|
||||
| (pin) "Pin a window"
|
||||
| (movefocus) "Move the focus in a direction"
|
||||
|
@ -148,4 +159,5 @@ hyprctl [<OPTIONS>]... <ARGUMENTS>
|
|||
| (setignoregrouplock) "Temporarily enable or disable binds:ignore_group_lock"
|
||||
| (global) "Execute a Global Shortcut using the GlobalShortcuts portal"
|
||||
| (submap) "Change the current mapping group"
|
||||
| (event) "Emits a custom event to socket2"
|
||||
;
|
||||
|
|
|
@ -1,145 +1,160 @@
|
|||
#compdef hyprctl
|
||||
|
||||
_hyprctl_cmd_2 () {
|
||||
_hyprctl_cmd_1 () {
|
||||
hyprctl monitors | awk '/Monitor/{ print $2 }'
|
||||
}
|
||||
|
||||
_hyprctl_cmd_3 () {
|
||||
hyprpm list | awk '/Plugin/{ print $4 }'
|
||||
}
|
||||
|
||||
_hyprctl_cmd_0 () {
|
||||
hyprctl clients | awk '/class/{print $2}'
|
||||
}
|
||||
|
||||
_hyprctl_cmd_1 () {
|
||||
_hyprctl_cmd_2 () {
|
||||
hyprctl devices | sed -n '/Keyboard at/{n; s/^\s\+//; p}'
|
||||
}
|
||||
|
||||
_hyprctl_cmd_0 () {
|
||||
hyprpm list | awk '/Plugin/{print $4}'
|
||||
}
|
||||
|
||||
_hyprctl () {
|
||||
local -a literals=("cyclenext" "globalshortcuts" "cursorpos" "bordersize" "renameworkspace" "animationstyle" "focuswindow" "0" "auto" "swapnext" "forceallowsinput" "moveactive" "activebordercolor" "alphafullscreen" "wayland" "layers" "minsize" "monitors" "1" "kill" "settiled" "3" "focusmonitor" "swapwindow" "moveoutofgroup" "notify" "movecursor" "setcursor" "seterror" "movecurrentworkspacetomonitor" "4" "nomaxsize" "forcenoanims" "setprop" "-i" "-q" "togglefloating" "workspacerules" "movetoworkspace" "disable" "setignoregrouplock" "workspaces" "movegroupwindow" "closewindow" "0" "--instance" "binds" "movewindow" "splitratio" "alpha" "denywindowfromgroup" "workspace" "configerrors" "togglegroup" "getoption" "forceopaque" "keepaspectratio" "killactive" "pass" "decorations" "devices" "focuscurrentorlast" "submap" "global" "alphafullscreenoverride" "forcerendererreload" "movewindowpixel" "headless" "version" "dpms" "resizeactive" "moveintogroup" "5" "alphaoverride" "setfloating" "rollinglog" "::=" "rounding" "layouts" "moveworkspacetomonitor" "exec" "alphainactiveoverride" "alterzorder" "fakefullscreen" "nofocus" "keyword" "forcenoborder" "forcenodim" "--quiet" "pin" "output" "forcenoblur" "togglespecialworkspace" "fullscreen" "toggleopaque" "focusworkspaceoncurrentmonitor" "next" "changegroupactive" "-j" "instances" "execr" "exit" "clients" "all" "--batch" "dismissnotify" "inactivebordercolor" "switchxkblayout" "movetoworkspacesilent" "tagwindow" "movewindoworgroup" "-r" "movefocus" "focusurgentorlast" "remove" "activeworkspace" "dispatch" "create" "centerwindow" "2" "hyprpaper" "-1" "reload" "alphainactive" "systeminfo" "plugin" "dimaround" "activewindow" "swapactiveworkspaces" "splash" "sendshortcut" "maxsize" "lockactivegroup" "windowdancecompat" "forceopaqueoverriden" "lockgroups" "movecursortocorner" "x11" "prev" "1" "resizewindowpixel" "forcenoshadow")
|
||||
local -a literals=("resizeactive" "2" "changegroupactive" "-r" "moveintogroup" "forceallowsinput" "4" "::=" "systeminfo" "all" "layouts" "setprop" "animationstyle" "switchxkblayout" "create" "denywindowfromgroup" "headless" "activebordercolor" "exec" "setcursor" "wayland" "focusurgentorlast" "workspacerules" "movecurrentworkspacetomonitor" "movetoworkspacesilent" "hyprpaper" "alpha" "inactivebordercolor" "movegroupwindow" "movecursortocorner" "movewindowpixel" "prev" "movewindow" "globalshortcuts" "clients" "dimaround" "setignoregrouplock" "splash" "execr" "monitors" "0" "forcenoborder" "-q" "animations" "1" "nomaxsize" "splitratio" "moveactive" "pass" "swapnext" "devices" "layers" "rounding" "lockactivegroup" "5" "moveworkspacetomonitor" "-f" "-i" "--quiet" "forcenodim" "pin" "0" "1" "forceopaque" "forcenoshadow" "setfloating" "minsize" "alphaoverride" "sendshortcut" "workspaces" "cyclenext" "alterzorder" "togglegroup" "lockgroups" "bordersize" "dpms" "focuscurrentorlast" "-1" "--batch" "notify" "remove" "instances" "1" "3" "moveoutofgroup" "killactive" "2" "movetoworkspace" "movecursor" "configerrors" "closewindow" "swapwindow" "tagwindow" "forcerendererreload" "centerwindow" "auto" "focuswindow" "seterror" "nofocus" "alphafullscreen" "binds" "version" "-h" "togglespecialworkspace" "fullscreen" "windowdancecompat" "0" "keyword" "toggleopaque" "3" "--instance" "togglefloating" "renameworkspace" "alphafullscreenoverride" "activeworkspace" "x11" "kill" "forceopaqueoverriden" "output" "global" "dispatch" "reload" "forcenoblur" "-j" "event" "--help" "disable" "-1" "activewindow" "keepaspectratio" "dismissnotify" "focusmonitor" "movefocus" "plugin" "exit" "workspace" "fullscreenstate" "getoption" "alphainactiveoverride" "alphainactive" "decorations" "settiled" "config-only" "descriptions" "resizewindowpixel" "fakefullscreen" "rollinglog" "swapactiveworkspaces" "submap" "next" "movewindoworgroup" "cursorpos" "forcenoanims" "focusworkspaceoncurrentmonitor" "maxsize")
|
||||
|
||||
local -A descriptions
|
||||
descriptions[1]="Focus the next window on a workspace"
|
||||
descriptions[3]="Get the current cursor pos in global layout coordinates"
|
||||
descriptions[5]="Rename a workspace"
|
||||
descriptions[7]="Focus the first window matching"
|
||||
descriptions[10]="Swap the focused window with the next window"
|
||||
descriptions[12]="Move the active window"
|
||||
descriptions[16]="List the layers"
|
||||
descriptions[18]="List active outputs with their properties"
|
||||
descriptions[20]="Get into a kill mode, where you can kill an app by clicking on it"
|
||||
descriptions[21]="Set the current window's floating state to false"
|
||||
descriptions[22]="ERROR"
|
||||
descriptions[23]="Focus a monitor"
|
||||
descriptions[24]="Swap the active window with another window"
|
||||
descriptions[25]="Move the active window out of a group"
|
||||
descriptions[26]="Send a notification using the built-in Hyprland notification system"
|
||||
descriptions[27]="Move the cursor to a specified position"
|
||||
descriptions[28]="Set the cursor theme and reloads the cursor manager"
|
||||
descriptions[29]="Set the hyprctl error string"
|
||||
descriptions[30]="Move the active workspace to a monitor"
|
||||
descriptions[31]="CONFUSED"
|
||||
descriptions[34]="Set a property of a window"
|
||||
descriptions[35]="Specify the Hyprland instance"
|
||||
descriptions[36]="Disable output"
|
||||
descriptions[37]="Toggle the current window's floating state"
|
||||
descriptions[38]="Get the list of defined workspace rules"
|
||||
descriptions[39]="Move the focused window to a workspace"
|
||||
descriptions[41]="Temporarily enable or disable binds:ignore_group_lock"
|
||||
descriptions[42]="List all workspaces with their properties"
|
||||
descriptions[43]="Swap the active window with the next or previous in a group"
|
||||
descriptions[44]="Close a specified window"
|
||||
descriptions[45]="WARNING"
|
||||
descriptions[46]="Specify the Hyprland instance"
|
||||
descriptions[47]="List all registered binds"
|
||||
descriptions[48]="Move the active window in a direction or to a monitor"
|
||||
descriptions[49]="Change the split ratio"
|
||||
descriptions[51]="Prohibit the active window from becoming or being inserted into group"
|
||||
descriptions[52]="Change the workspace"
|
||||
descriptions[53]="List all current config parsing errors"
|
||||
descriptions[54]="Toggle the current active window into a group"
|
||||
descriptions[55]="Get the config option status (values)"
|
||||
descriptions[58]="Close the active window"
|
||||
descriptions[59]="Pass the key to a specified window"
|
||||
descriptions[60]="List all decorations and their info"
|
||||
descriptions[61]="List all connected keyboards and mice"
|
||||
descriptions[62]="Switch focus from current to previously focused window"
|
||||
descriptions[63]="Change the current mapping group"
|
||||
descriptions[64]="Execute a Global Shortcut using the GlobalShortcuts portal"
|
||||
descriptions[66]="Force the renderer to reload all resources and outputs"
|
||||
descriptions[67]="Move a selected window"
|
||||
descriptions[69]="Print the Hyprland version: flags, commit and branch of build"
|
||||
descriptions[70]="Set all monitors' DPMS status"
|
||||
descriptions[71]="Resize the active window"
|
||||
descriptions[72]="Move the active window into a group"
|
||||
descriptions[73]="OK"
|
||||
descriptions[75]="Set the current window's floating state to true"
|
||||
descriptions[76]="Print tail of the log"
|
||||
descriptions[79]="List all layouts available (including plugin ones)"
|
||||
descriptions[80]="Move a workspace to a monitor"
|
||||
descriptions[81]="Execute a shell command"
|
||||
descriptions[83]="Modify the window stack order of the active or specified window"
|
||||
descriptions[84]="Toggle the focused window's internal fullscreen state"
|
||||
descriptions[86]="Issue a keyword to call a config keyword dynamically"
|
||||
descriptions[89]="Disable output"
|
||||
descriptions[90]="Pin a window"
|
||||
descriptions[91]="Allows adding/removing fake outputs to a specific backend"
|
||||
descriptions[93]="Toggle a special workspace on/off"
|
||||
descriptions[94]="Toggle the focused window's fullscreen state"
|
||||
descriptions[95]="Toggle the current window to always be opaque"
|
||||
descriptions[96]="Focus the requested workspace"
|
||||
descriptions[98]="Switch to the next window in a group"
|
||||
descriptions[99]="Output in JSON format"
|
||||
descriptions[100]="List all running Hyprland instances and their info"
|
||||
descriptions[101]="Execute a raw shell command"
|
||||
descriptions[102]="Exit the compositor with no questions asked"
|
||||
descriptions[103]="List all windows with their properties"
|
||||
descriptions[105]="Execute a batch of commands separated by ;"
|
||||
descriptions[106]="Dismiss all or up to amount of notifications"
|
||||
descriptions[108]="Set the xkb layout index for a keyboard"
|
||||
descriptions[109]="Move window doesnt switch to the workspace"
|
||||
descriptions[110]="Apply a tag to the window"
|
||||
descriptions[111]="Behave as moveintogroup"
|
||||
descriptions[112]="Refresh state after issuing the command"
|
||||
descriptions[113]="Move the focus in a direction"
|
||||
descriptions[114]="Focus the urgent window or the last window"
|
||||
descriptions[116]="Get the active workspace name and its properties"
|
||||
descriptions[117]="Issue a dispatch to call a keybind dispatcher with an arg"
|
||||
descriptions[119]="Center the active window"
|
||||
descriptions[120]="HINT"
|
||||
descriptions[121]="Interact with hyprpaper if present"
|
||||
descriptions[122]="No Icon"
|
||||
descriptions[123]="Force reload the config"
|
||||
descriptions[125]="Print system info"
|
||||
descriptions[126]="Interact with a plugin"
|
||||
descriptions[128]="Get the active window name and its properties"
|
||||
descriptions[129]="Swap the active workspaces between two monitors"
|
||||
descriptions[130]="Print the current random splash"
|
||||
descriptions[131]="On shortcut X sends shortcut Y to a specified window"
|
||||
descriptions[133]="Lock the focused group"
|
||||
descriptions[136]="Lock the groups"
|
||||
descriptions[137]="Move the cursor to the corner of the active window"
|
||||
descriptions[140]="INFO"
|
||||
descriptions[141]="Resize a selected window"
|
||||
descriptions[1]="Resize the active window"
|
||||
descriptions[2]="Fullscreen"
|
||||
descriptions[3]="Switch to the next window in a group"
|
||||
descriptions[4]="Refresh state after issuing the command"
|
||||
descriptions[5]="Move the active window into a group"
|
||||
descriptions[7]="CONFUSED"
|
||||
descriptions[9]="Print system info"
|
||||
descriptions[11]="List all layouts available (including plugin ones)"
|
||||
descriptions[12]="Set a property of a window"
|
||||
descriptions[14]="Set the xkb layout index for a keyboard"
|
||||
descriptions[16]="Prohibit the active window from becoming or being inserted into group"
|
||||
descriptions[19]="Execute a shell command"
|
||||
descriptions[20]="Set the cursor theme and reloads the cursor manager"
|
||||
descriptions[22]="Focus the urgent window or the last window"
|
||||
descriptions[23]="Get the list of defined workspace rules"
|
||||
descriptions[24]="Move the active workspace to a monitor"
|
||||
descriptions[25]="Move window doesnt switch to the workspace"
|
||||
descriptions[26]="Interact with hyprpaper if present"
|
||||
descriptions[29]="Swap the active window with the next or previous in a group"
|
||||
descriptions[30]="Move the cursor to the corner of the active window"
|
||||
descriptions[31]="Move a selected window"
|
||||
descriptions[33]="Move the active window in a direction or to a monitor"
|
||||
descriptions[34]="Lists all global shortcuts"
|
||||
descriptions[35]="List all windows with their properties"
|
||||
descriptions[37]="Temporarily enable or disable binds:ignore_group_lock"
|
||||
descriptions[38]="Print the current random splash"
|
||||
descriptions[39]="Execute a raw shell command"
|
||||
descriptions[40]="List active outputs with their properties"
|
||||
descriptions[43]="Disable output"
|
||||
descriptions[44]="Gets the current config info about animations and beziers"
|
||||
descriptions[47]="Change the split ratio"
|
||||
descriptions[48]="Move the active window"
|
||||
descriptions[49]="Pass the key to a specified window"
|
||||
descriptions[50]="Swap the focused window with the next window"
|
||||
descriptions[51]="List all connected keyboards and mice"
|
||||
descriptions[52]="List the layers"
|
||||
descriptions[54]="Lock the focused group"
|
||||
descriptions[55]="OK"
|
||||
descriptions[56]="Move a workspace to a monitor"
|
||||
descriptions[58]="Specify the Hyprland instance"
|
||||
descriptions[59]="Disable output"
|
||||
descriptions[61]="Pin a window"
|
||||
descriptions[62]="WARNING"
|
||||
descriptions[63]="INFO"
|
||||
descriptions[66]="Set the current window's floating state to true"
|
||||
descriptions[69]="On shortcut X sends shortcut Y to a specified window"
|
||||
descriptions[70]="List all workspaces with their properties"
|
||||
descriptions[71]="Focus the next window on a workspace"
|
||||
descriptions[72]="Modify the window stack order of the active or specified window"
|
||||
descriptions[73]="Toggle the current active window into a group"
|
||||
descriptions[74]="Lock the groups"
|
||||
descriptions[76]="Set all monitors' DPMS status"
|
||||
descriptions[77]="Switch focus from current to previously focused window"
|
||||
descriptions[78]="No Icon"
|
||||
descriptions[79]="Execute a batch of commands separated by ;"
|
||||
descriptions[80]="Send a notification using the built-in Hyprland notification system"
|
||||
descriptions[82]="List all running Hyprland instances and their info"
|
||||
descriptions[83]="Maximize no fullscreen"
|
||||
descriptions[84]="Maximize and fullscreen"
|
||||
descriptions[85]="Move the active window out of a group"
|
||||
descriptions[86]="Close the active window"
|
||||
descriptions[87]="HINT"
|
||||
descriptions[88]="Move the focused window to a workspace"
|
||||
descriptions[89]="Move the cursor to a specified position"
|
||||
descriptions[90]="List all current config parsing errors"
|
||||
descriptions[91]="Close a specified window"
|
||||
descriptions[92]="Swap the active window with another window"
|
||||
descriptions[93]="Apply a tag to the window"
|
||||
descriptions[94]="Force the renderer to reload all resources and outputs"
|
||||
descriptions[95]="Center the active window"
|
||||
descriptions[97]="Focus the first window matching"
|
||||
descriptions[98]="Set the hyprctl error string"
|
||||
descriptions[101]="List all registered binds"
|
||||
descriptions[102]="Print the Hyprland version: flags, commit and branch of build"
|
||||
descriptions[103]="Prints the help message"
|
||||
descriptions[104]="Toggle a special workspace on/off"
|
||||
descriptions[105]="Toggle the focused window's fullscreen state"
|
||||
descriptions[107]="None"
|
||||
descriptions[108]="Issue a keyword to call a config keyword dynamically"
|
||||
descriptions[109]="Toggle the current window to always be opaque"
|
||||
descriptions[110]="ERROR"
|
||||
descriptions[111]="Specify the Hyprland instance"
|
||||
descriptions[112]="Toggle the current window's floating state"
|
||||
descriptions[113]="Rename a workspace"
|
||||
descriptions[115]="Get the active workspace name and its properties"
|
||||
descriptions[117]="Get into a kill mode, where you can kill an app by clicking on it"
|
||||
descriptions[119]="Allows adding/removing fake outputs to a specific backend"
|
||||
descriptions[120]="Execute a Global Shortcut using the GlobalShortcuts portal"
|
||||
descriptions[121]="Issue a dispatch to call a keybind dispatcher with an arg"
|
||||
descriptions[122]="Force reload the config"
|
||||
descriptions[124]="Output in JSON format"
|
||||
descriptions[125]="Emits a custom event to socket2"
|
||||
descriptions[126]="Prints the help message"
|
||||
descriptions[128]="Current"
|
||||
descriptions[129]="Get the active window name and its properties"
|
||||
descriptions[131]="Dismiss all or up to amount of notifications"
|
||||
descriptions[132]="Focus a monitor"
|
||||
descriptions[133]="Move the focus in a direction"
|
||||
descriptions[134]="Interact with a plugin"
|
||||
descriptions[135]="Exit the compositor with no questions asked"
|
||||
descriptions[136]="Change the workspace"
|
||||
descriptions[137]="Sets the focused window’s fullscreen mode and the one sent to the client"
|
||||
descriptions[138]="Get the config option status (values)"
|
||||
descriptions[141]="List all decorations and their info"
|
||||
descriptions[142]="Set the current window's floating state to false"
|
||||
descriptions[144]="Return a parsable JSON with all the config options, descriptions, value types and ranges"
|
||||
descriptions[145]="Resize a selected window"
|
||||
descriptions[146]="Toggle the focused window's internal fullscreen state"
|
||||
descriptions[147]="Print tail of the log"
|
||||
descriptions[148]="Swap the active workspaces between two monitors"
|
||||
descriptions[149]="Change the current mapping group"
|
||||
descriptions[151]="Behave as moveintogroup"
|
||||
descriptions[152]="Get the current cursor pos in global layout coordinates"
|
||||
descriptions[154]="Focus the requested workspace"
|
||||
|
||||
local -A literal_transitions
|
||||
literal_transitions[1]="([106]=2 [76]=3 [34]=4 [36]=5 [2]=3 [3]=3 [79]=3 [108]=6 [38]=3 [112]=5 [42]=3 [47]=3 [116]=3 [86]=7 [117]=9 [53]=3 [89]=5 [55]=3 [91]=10 [121]=3 [123]=3 [125]=3 [16]=3 [60]=11 [61]=3 [18]=12 [126]=13 [20]=3 [128]=3 [130]=3 [26]=14 [69]=3 [99]=5 [100]=3 [28]=3 [29]=15 [103]=3 [105]=5)"
|
||||
literal_transitions[4]="([74]=18 [14]=3 [33]=18 [56]=18 [57]=18 [92]=18 [107]=3 [124]=3 [78]=2 [17]=3 [127]=18 [4]=2 [6]=3 [65]=18 [132]=3 [134]=18 [82]=18 [135]=18 [85]=18 [32]=18 [50]=3 [13]=3 [87]=18 [11]=18 [88]=18 [142]=18)"
|
||||
literal_transitions[8]="([106]=2 [76]=3 [34]=4 [2]=3 [3]=3 [79]=3 [108]=6 [38]=3 [42]=3 [47]=3 [116]=3 [86]=7 [117]=9 [53]=3 [55]=3 [91]=10 [121]=3 [123]=3 [125]=3 [16]=3 [60]=11 [61]=3 [18]=12 [126]=13 [20]=3 [128]=3 [130]=3 [26]=14 [69]=3 [100]=3 [28]=3 [29]=15 [103]=3)"
|
||||
literal_transitions[9]="([102]=3 [131]=3 [133]=3 [1]=3 [75]=3 [37]=3 [109]=3 [110]=3 [39]=3 [111]=3 [5]=3 [80]=3 [41]=3 [81]=3 [114]=3 [7]=3 [43]=3 [44]=3 [83]=3 [84]=3 [48]=3 [49]=3 [10]=3 [51]=3 [52]=3 [54]=3 [12]=3 [113]=3 [90]=3 [119]=3 [58]=3 [93]=3 [59]=3 [94]=3 [95]=3 [62]=3 [63]=3 [129]=3 [96]=3 [64]=3 [21]=3 [98]=3 [23]=3 [24]=3 [66]=3 [67]=3 [136]=3 [137]=3 [25]=3 [27]=3 [70]=3 [101]=3 [71]=3 [141]=3 [30]=3 [72]=3)"
|
||||
literal_transitions[10]="([118]=21 [115]=17)"
|
||||
literal_transitions[12]="([104]=3)"
|
||||
literal_transitions[14]="([22]=2 [120]=2 [31]=2 [140]=2 [122]=2 [45]=2 [73]=2)"
|
||||
literal_transitions[15]="([40]=3)"
|
||||
literal_transitions[16]="([139]=3 [97]=3)"
|
||||
literal_transitions[18]="([19]=3 [8]=3)"
|
||||
literal_transitions[19]="([77]=20)"
|
||||
literal_transitions[20]="([35]=5 [46]=5)"
|
||||
literal_transitions[21]="([9]=3 [68]=3 [15]=3 [138]=3)"
|
||||
literal_transitions[1]="([121]=15 [44]=3 [126]=22 [82]=3 [4]=22 [52]=3 [51]=3 [129]=3 [90]=3 [59]=22 [9]=3 [11]=3 [12]=4 [131]=5 [14]=6 [98]=7 [102]=3 [103]=22 [134]=8 [101]=3 [138]=3 [23]=3 [20]=3 [141]=9 [26]=3 [144]=3 [108]=10 [147]=11 [70]=3 [34]=3 [35]=3 [79]=22 [115]=3 [38]=3 [152]=3 [117]=3 [122]=14 [124]=22 [40]=12 [43]=22 [80]=16 [119]=13)"
|
||||
literal_transitions[2]="([82]=3 [52]=3 [51]=3 [129]=3 [9]=3 [90]=3 [11]=3 [12]=4 [131]=5 [14]=6 [98]=7 [102]=3 [134]=8 [101]=3 [23]=3 [20]=3 [138]=3 [141]=9 [26]=3 [144]=3 [108]=10 [147]=11 [70]=3 [34]=3 [35]=3 [115]=3 [38]=3 [152]=3 [117]=3 [40]=12 [119]=13 [122]=14 [121]=15 [80]=16 [44]=3)"
|
||||
literal_transitions[4]="([140]=3 [64]=17 [65]=17 [46]=17 [106]=17 [28]=3 [27]=3 [53]=5 [6]=17 [67]=3 [68]=17 [130]=17 [114]=17 [13]=3 [75]=5 [100]=3 [36]=17 [153]=17 [99]=17 [60]=17 [118]=17 [42]=17 [18]=3 [139]=17 [155]=3 [123]=17)"
|
||||
literal_transitions[7]="([127]=3)"
|
||||
literal_transitions[11]="([57]=3)"
|
||||
literal_transitions[12]="([10]=3)"
|
||||
literal_transitions[13]="([15]=20 [81]=23)"
|
||||
literal_transitions[14]="([143]=3)"
|
||||
literal_transitions[15]="([1]=3 [85]=3 [3]=3 [86]=3 [5]=3 [88]=3 [89]=3 [91]=3 [92]=3 [93]=3 [94]=3 [95]=3 [97]=3 [16]=3 [19]=3 [104]=3 [22]=3 [105]=3 [24]=3 [25]=3 [29]=3 [30]=3 [31]=3 [109]=3 [112]=3 [33]=3 [113]=3 [37]=3 [39]=3 [120]=3 [125]=3 [47]=3 [48]=3 [49]=3 [50]=3 [54]=3 [56]=3 [132]=3 [133]=3 [135]=3 [136]=3 [61]=3 [137]=21 [142]=3 [66]=3 [145]=3 [146]=3 [69]=3 [148]=3 [71]=3 [72]=3 [73]=3 [74]=3 [149]=3 [76]=3 [77]=3 [151]=3 [154]=3)"
|
||||
literal_transitions[16]="([87]=5 [7]=5 [110]=5 [62]=5 [78]=5 [55]=5 [63]=5)"
|
||||
literal_transitions[17]="([41]=3 [45]=3)"
|
||||
literal_transitions[18]="([8]=24)"
|
||||
literal_transitions[19]="([32]=3 [150]=3)"
|
||||
literal_transitions[20]="([96]=3 [17]=3 [116]=3 [21]=3)"
|
||||
literal_transitions[21]="([107]=3 [83]=3 [128]=3 [2]=3 [84]=3)"
|
||||
literal_transitions[24]="([58]=22 [111]=22)"
|
||||
|
||||
local -A match_anything_transitions
|
||||
match_anything_transitions=([2]=3 [1]=8 [7]=3 [16]=3 [11]=3 [6]=16 [15]=19 [8]=8 [3]=19 [17]=3 [13]=3 [12]=19)
|
||||
match_anything_transitions=([7]=18 [8]=3 [1]=2 [23]=3 [6]=19 [5]=3 [3]=18 [19]=3 [12]=18 [9]=3 [10]=3 [14]=18 [11]=18 [2]=2)
|
||||
|
||||
declare -A subword_transitions
|
||||
|
||||
|
@ -199,7 +214,7 @@ _hyprctl () {
|
|||
fi
|
||||
done
|
||||
fi
|
||||
local -A commands=([6]=1 [17]=2 [13]=3 [11]=0)
|
||||
local -A commands=([8]=0 [23]=1 [9]=3 [6]=2)
|
||||
|
||||
if [[ -v "commands[$state]" ]]; then
|
||||
local command_id=${commands[$state]}
|
||||
|
@ -252,4 +267,8 @@ _hyprctl () {
|
|||
return 0
|
||||
}
|
||||
|
||||
if [[ $ZSH_EVAL_CONTEXT =~ :file$ ]]; then
|
||||
compdef _hyprctl hyprctl
|
||||
else
|
||||
_hyprctl
|
||||
fi
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <print>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
@ -26,6 +27,7 @@
|
|||
#include <regex>
|
||||
#include <sys/socket.h>
|
||||
#include <hyprutils/string/String.hpp>
|
||||
#include <cstring>
|
||||
using namespace Hyprutils::String;
|
||||
|
||||
#include "Strings.hpp"
|
||||
|
@ -43,11 +45,11 @@ struct SInstanceData {
|
|||
bool valid = true;
|
||||
};
|
||||
|
||||
void log(std::string str) {
|
||||
void log(const std::string& str) {
|
||||
if (quiet)
|
||||
return;
|
||||
|
||||
std::cout << str << "\n";
|
||||
std::println("{}", str);
|
||||
}
|
||||
|
||||
std::string getRuntimeDir() {
|
||||
|
@ -104,7 +106,7 @@ std::vector<SInstanceData> instances() {
|
|||
static volatile bool sigintReceived = false;
|
||||
void intHandler(int sig) {
|
||||
sigintReceived = true;
|
||||
std::cout << "[hyprctl] SIGINT received, closing connection" << std::endl;
|
||||
std::println("[hyprctl] SIGINT received, closing connection");
|
||||
}
|
||||
|
||||
int rollingRead(const int socket) {
|
||||
|
@ -113,13 +115,13 @@ int rollingRead(const int socket) {
|
|||
|
||||
constexpr size_t BUFFER_SIZE = 8192;
|
||||
std::array<char, BUFFER_SIZE> buffer = {0};
|
||||
int sizeWritten = 0;
|
||||
std::cout << "[hyprctl] reading from socket following up log:" << std::endl;
|
||||
long sizeWritten = 0;
|
||||
std::println("[hyprctl] reading from socket following up log:");
|
||||
while (!sigintReceived) {
|
||||
sizeWritten = read(socket, buffer.data(), BUFFER_SIZE);
|
||||
if (sizeWritten < 0 && errno != EAGAIN) {
|
||||
if (errno != EINTR)
|
||||
std::cout << "Couldn't read (5) " << strerror(errno) << ":" << errno << std::endl;
|
||||
std::println("Couldn't read (5): {}: {}", strerror(errno), errno);
|
||||
close(socket);
|
||||
return 5;
|
||||
}
|
||||
|
@ -128,7 +130,7 @@ int rollingRead(const int socket) {
|
|||
break;
|
||||
|
||||
if (sizeWritten > 0) {
|
||||
std::cout << std::string(buffer.data(), sizeWritten);
|
||||
std::println("{}", std::string(buffer.data(), sizeWritten));
|
||||
buffer.fill('\0');
|
||||
}
|
||||
|
||||
|
@ -286,12 +288,12 @@ void instancesRequest(bool json) {
|
|||
std::vector<SInstanceData> inst = instances();
|
||||
|
||||
if (!json) {
|
||||
for (auto& el : inst) {
|
||||
for (auto const& el : inst) {
|
||||
result += std::format("instance {}:\n\ttime: {}\n\tpid: {}\n\twl socket: {}\n\n", el.id, el.time, el.pid, el.wlSocket);
|
||||
}
|
||||
} else {
|
||||
result += '[';
|
||||
for (auto& el : inst) {
|
||||
for (auto const& el : inst) {
|
||||
result += std::format(R"#(
|
||||
{{
|
||||
"instance": "{}",
|
||||
|
@ -322,7 +324,7 @@ int main(int argc, char** argv) {
|
|||
bool parseArgs = true;
|
||||
|
||||
if (argc < 2) {
|
||||
std::cout << USAGE << std::endl;
|
||||
std::println("{}", USAGE);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -359,7 +361,7 @@ int main(int argc, char** argv) {
|
|||
++i;
|
||||
|
||||
if (i >= ARGS.size()) {
|
||||
std::cout << USAGE << std::endl;
|
||||
std::println("{}", USAGE);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -370,24 +372,24 @@ int main(int argc, char** argv) {
|
|||
const std::string& cmd = ARGS[0];
|
||||
|
||||
if (cmd == "hyprpaper") {
|
||||
std::cout << HYPRPAPER_HELP << std::endl;
|
||||
std::println("{}", HYPRPAPER_HELP);
|
||||
} else if (cmd == "notify") {
|
||||
std::cout << NOTIFY_HELP << std::endl;
|
||||
std::println("{}", NOTIFY_HELP);
|
||||
} else if (cmd == "output") {
|
||||
std::cout << OUTPUT_HELP << std::endl;
|
||||
std::println("{}", OUTPUT_HELP);
|
||||
} else if (cmd == "plugin") {
|
||||
std::cout << PLUGIN_HELP << std::endl;
|
||||
std::println("{}", PLUGIN_HELP);
|
||||
} else if (cmd == "setprop") {
|
||||
std::cout << SETPROP_HELP << std::endl;
|
||||
std::println("{}", SETPROP_HELP);
|
||||
} else if (cmd == "switchxkblayout") {
|
||||
std::cout << SWITCHXKBLAYOUT_HELP << std::endl;
|
||||
std::println("{}", SWITCHXKBLAYOUT_HELP);
|
||||
} else {
|
||||
std::cout << USAGE << std::endl;
|
||||
std::println("{}", USAGE);
|
||||
}
|
||||
|
||||
return 1;
|
||||
} else {
|
||||
std::cout << USAGE << std::endl;
|
||||
std::println("{}", USAGE);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -398,7 +400,7 @@ int main(int argc, char** argv) {
|
|||
}
|
||||
|
||||
if (fullRequest.empty()) {
|
||||
std::cout << USAGE << std::endl;
|
||||
std::println("{}", USAGE);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -475,7 +477,7 @@ int main(int argc, char** argv) {
|
|||
else if (fullRequest.contains("/decorations"))
|
||||
exitStatus = request(fullRequest, 1);
|
||||
else if (fullRequest.contains("/--help"))
|
||||
std::cout << USAGE << std::endl;
|
||||
std::println("{}", USAGE);
|
||||
else if (fullRequest.contains("/rollinglog") && needRoll)
|
||||
exitStatus = request(fullRequest, 0, true);
|
||||
else {
|
||||
|
|
|
@ -1,10 +1,26 @@
|
|||
executable('hyprctl', 'main.cpp',
|
||||
executable(
|
||||
'hyprctl',
|
||||
'main.cpp',
|
||||
dependencies: [
|
||||
dependency('hyprutils', version: '>= 0.1.1'),
|
||||
],
|
||||
install: true
|
||||
install: true,
|
||||
)
|
||||
|
||||
install_data('hyprctl.bash', install_dir: join_paths(get_option('datadir'), 'bash-completion/completions'), install_tag: 'runtime', rename: 'hyprctl')
|
||||
install_data('hyprctl.fish', install_dir: join_paths(get_option('datadir'), 'fish/vendor_completions.d'), install_tag: 'runtime')
|
||||
install_data('hyprctl.zsh', install_dir: join_paths(get_option('datadir'), 'zsh/site-functions'), install_tag: 'runtime', rename: '_hyprctl')
|
||||
install_data(
|
||||
'hyprctl.bash',
|
||||
install_dir: join_paths(get_option('datadir'), 'bash-completion/completions'),
|
||||
install_tag: 'runtime',
|
||||
rename: 'hyprctl',
|
||||
)
|
||||
install_data(
|
||||
'hyprctl.fish',
|
||||
install_dir: join_paths(get_option('datadir'), 'fish/vendor_completions.d'),
|
||||
install_tag: 'runtime',
|
||||
)
|
||||
install_data(
|
||||
'hyprctl.zsh',
|
||||
install_dir: join_paths(get_option('datadir'), 'zsh/site-functions'),
|
||||
install_tag: 'runtime',
|
||||
rename: '_hyprctl',
|
||||
)
|
||||
|
|
|
@ -2,6 +2,10 @@ _hyprpm_cmd_0 () {
|
|||
hyprpm list | awk '/Plugin/{print $4}'
|
||||
}
|
||||
|
||||
_hyprpm_cmd_1 () {
|
||||
hyprpm list | awk '/Repository/{print $4}' | sed 's/:$//'
|
||||
}
|
||||
|
||||
_hyprpm () {
|
||||
if [[ $(type -t _get_comp_words_by_ref) != function ]]; then
|
||||
echo _get_comp_words_by_ref: function not defined. Make sure the bash-completions system package is installed
|
||||
|
@ -11,16 +15,13 @@ _hyprpm () {
|
|||
local words cword
|
||||
_get_comp_words_by_ref -n "$COMP_WORDBREAKS" words cword
|
||||
|
||||
local -a literals=("-n" "::=" "list" "disable" "--help" "update" "add" "--verbose" "-v" "--force" "remove" "enable" "--notify" "-h" "reload" "-f")
|
||||
|
||||
declare -a literals=(--no-shallow -n ::= disable list --help update add --verbose -v --force -s remove enable --notify -h reload -f)
|
||||
declare -A literal_transitions
|
||||
literal_transitions[0]="([9]=6 [2]=2 [7]=6 [8]=6 [4]=6 [10]=2 [11]=3 [5]=2 [13]=6 [3]=3 [14]=2 [15]=6 [6]=2)"
|
||||
literal_transitions[1]="([10]=2 [11]=3 [3]=3 [2]=2 [14]=2 [5]=2 [6]=2)"
|
||||
literal_transitions[4]="([1]=5)"
|
||||
literal_transitions[5]="([0]=6 [12]=6)"
|
||||
|
||||
declare -A match_anything_transitions
|
||||
match_anything_transitions=([3]=2 [2]=4 [0]=1 [1]=1)
|
||||
literal_transitions[0]="([0]=7 [3]=3 [4]=4 [8]=7 [9]=7 [6]=4 [7]=4 [11]=7 [5]=7 [10]=7 [12]=2 [13]=3 [15]=7 [16]=4 [17]=7)"
|
||||
literal_transitions[1]="([12]=2 [13]=3 [3]=3 [4]=4 [16]=4 [6]=4 [7]=4)"
|
||||
literal_transitions[5]="([2]=6)"
|
||||
literal_transitions[6]="([1]=7 [14]=7)"
|
||||
declare -A match_anything_transitions=([1]=1 [4]=5 [3]=4 [2]=4 [0]=1)
|
||||
declare -A subword_transitions
|
||||
|
||||
local state=0
|
||||
|
@ -58,21 +59,9 @@ _hyprpm () {
|
|||
done
|
||||
|
||||
|
||||
local -a matches=()
|
||||
|
||||
local prefix="${words[$cword]}"
|
||||
|
||||
local shortest_suffix="$word"
|
||||
for ((i=0; i < ${#COMP_WORDBREAKS}; i++)); do
|
||||
local char="${COMP_WORDBREAKS:$i:1}"
|
||||
local candidate="${word##*$char}"
|
||||
if [[ ${#candidate} -lt ${#shortest_suffix} ]]; then
|
||||
shortest_suffix=$candidate
|
||||
fi
|
||||
done
|
||||
local superfluous_prefix=""
|
||||
if [[ "$shortest_suffix" != "$word" ]]; then
|
||||
local superfluous_prefix=${word%$shortest_suffix}
|
||||
fi
|
||||
|
||||
if [[ -v "literal_transitions[$state]" ]]; then
|
||||
local state_transitions_initializer=${literal_transitions[$state]}
|
||||
declare -A state_transitions
|
||||
|
@ -81,25 +70,38 @@ _hyprpm () {
|
|||
for literal_id in "${!state_transitions[@]}"; do
|
||||
local literal="${literals[$literal_id]}"
|
||||
if [[ $literal = "${prefix}"* ]]; then
|
||||
local completion=${literal#"$superfluous_prefix"}
|
||||
COMPREPLY+=("$completion ")
|
||||
matches+=("$literal ")
|
||||
fi
|
||||
done
|
||||
fi
|
||||
declare -A commands
|
||||
commands=([3]=0)
|
||||
commands=([3]=0 [2]=1)
|
||||
if [[ -v "commands[$state]" ]]; then
|
||||
local command_id=${commands[$state]}
|
||||
local completions=()
|
||||
mapfile -t completions < <(_hyprpm_cmd_${command_id} "$prefix" | cut -f1)
|
||||
readarray -t completions < <(_hyprpm_cmd_${command_id} "$prefix" | cut -f1)
|
||||
for item in "${completions[@]}"; do
|
||||
if [[ $item = "${prefix}"* ]]; then
|
||||
COMPREPLY+=("$item")
|
||||
matches+=("$item")
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
|
||||
local shortest_suffix="$prefix"
|
||||
for ((i=0; i < ${#COMP_WORDBREAKS}; i++)); do
|
||||
local char="${COMP_WORDBREAKS:$i:1}"
|
||||
local candidate=${prefix##*$char}
|
||||
if [[ ${#candidate} -lt ${#shortest_suffix} ]]; then
|
||||
shortest_suffix=$candidate
|
||||
fi
|
||||
done
|
||||
local superfluous_prefix=""
|
||||
if [[ "$shortest_suffix" != "$prefix" ]]; then
|
||||
local superfluous_prefix=${prefix%$shortest_suffix}
|
||||
fi
|
||||
COMPREPLY=("${matches[@]#$superfluous_prefix}")
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,11 @@ function _hyprpm_1
|
|||
hyprpm list | awk '/Plugin/{print $4}'
|
||||
end
|
||||
|
||||
function _hyprpm_2
|
||||
set 1 $argv[1]
|
||||
hyprpm list | awk '/Repository/{print $4}' | sed 's/:$//'
|
||||
end
|
||||
|
||||
function _hyprpm
|
||||
set COMP_LINE (commandline --cut-at-cursor)
|
||||
|
||||
|
@ -14,49 +19,51 @@ function _hyprpm
|
|||
set COMP_CWORD (count $COMP_WORDS)
|
||||
end
|
||||
|
||||
set --local literals "-n" "::=" "list" "disable" "--help" "update" "add" "--verbose" "-v" "--force" "remove" "enable" "--notify" "-h" "reload" "-f"
|
||||
set literals "--no-shallow" "-n" "::=" "disable" "list" "--help" "update" "add" "--verbose" "-v" "--force" "-s" "remove" "enable" "--notify" "-h" "reload" "-f"
|
||||
|
||||
set --local descriptions
|
||||
set descriptions[1] "Send a hyprland notification for important events (e.g. load fail)"
|
||||
set descriptions[3] "List all installed plugins"
|
||||
set descriptions
|
||||
set descriptions[1] "Disable shallow cloning of Hyprland sources"
|
||||
set descriptions[2] "Send a hyprland notification for important events (e.g. load fail)"
|
||||
set descriptions[4] "Unload a plugin"
|
||||
set descriptions[5] "Show help menu"
|
||||
set descriptions[6] "Check and update all plugins if needed"
|
||||
set descriptions[7] "Install a new plugin repository from git"
|
||||
set descriptions[8] "Enable too much loggin"
|
||||
set descriptions[5] "List all installed plugins"
|
||||
set descriptions[6] "Show help menu"
|
||||
set descriptions[7] "Check and update all plugins if needed"
|
||||
set descriptions[8] "Install a new plugin repository from git"
|
||||
set descriptions[9] "Enable too much loggin"
|
||||
set descriptions[10] "Force an operation ignoring checks (e.g. update -f)"
|
||||
set descriptions[11] "Remove a plugin repository"
|
||||
set descriptions[12] "Load a plugin"
|
||||
set descriptions[13] "Send a hyprland notification for important events (e.g. load fail)"
|
||||
set descriptions[14] "Show help menu"
|
||||
set descriptions[15] "Reload all plugins"
|
||||
set descriptions[16] "Force an operation ignoring checks (e.g. update -f)"
|
||||
set descriptions[10] "Enable too much loggin"
|
||||
set descriptions[11] "Force an operation ignoring checks (e.g. update -f)"
|
||||
set descriptions[12] "Disable shallow cloning of Hyprland sources"
|
||||
set descriptions[13] "Remove a plugin repository"
|
||||
set descriptions[14] "Load a plugin"
|
||||
set descriptions[15] "Send a hyprland notification for important events (e.g. load fail)"
|
||||
set descriptions[16] "Show help menu"
|
||||
set descriptions[17] "Reload all plugins"
|
||||
set descriptions[18] "Force an operation ignoring checks (e.g. update -f)"
|
||||
|
||||
set --local literal_transitions
|
||||
set literal_transitions[1] "set inputs 10 3 8 9 5 11 12 6 14 4 15 16 7; set tos 7 3 7 7 7 3 4 3 7 4 3 7 3"
|
||||
set literal_transitions[2] "set inputs 11 12 4 3 15 6 7; set tos 3 4 4 3 3 3 3"
|
||||
set literal_transitions[5] "set inputs 2; set tos 6"
|
||||
set literal_transitions[6] "set inputs 1 13; set tos 7 7"
|
||||
set literal_transitions
|
||||
set literal_transitions[1] "set inputs 1 4 5 9 10 7 8 12 6 11 13 14 16 17 18; set tos 8 4 5 8 8 5 5 8 8 8 3 4 8 5 8"
|
||||
set literal_transitions[2] "set inputs 13 14 4 5 17 7 8; set tos 3 4 4 5 5 5 5"
|
||||
set literal_transitions[6] "set inputs 3; set tos 7"
|
||||
set literal_transitions[7] "set inputs 2 15; set tos 8 8"
|
||||
|
||||
set --local match_anything_transitions_from 4 3 1 2
|
||||
set --local match_anything_transitions_to 3 5 2 2
|
||||
set match_anything_transitions_from 2 5 4 3 1
|
||||
set match_anything_transitions_to 2 6 5 5 2
|
||||
|
||||
set --local state 1
|
||||
set --local word_index 2
|
||||
set state 1
|
||||
set word_index 2
|
||||
while test $word_index -lt $COMP_CWORD
|
||||
set --local -- word $COMP_WORDS[$word_index]
|
||||
set -- word $COMP_WORDS[$word_index]
|
||||
|
||||
if set --query literal_transitions[$state] && test -n $literal_transitions[$state]
|
||||
set --local --erase inputs
|
||||
set --local --erase tos
|
||||
set --erase inputs
|
||||
set --erase tos
|
||||
eval $literal_transitions[$state]
|
||||
|
||||
if contains -- $word $literals
|
||||
set --local literal_matched 0
|
||||
set literal_matched 0
|
||||
for literal_id in (seq 1 (count $literals))
|
||||
if test $literals[$literal_id] = $word
|
||||
set --local index (contains --index -- $literal_id $inputs)
|
||||
set index (contains --index -- $literal_id $inputs)
|
||||
set state $tos[$index]
|
||||
set word_index (math $word_index + 1)
|
||||
set literal_matched 1
|
||||
|
@ -70,7 +77,7 @@ function _hyprpm
|
|||
end
|
||||
|
||||
if set --query match_anything_transitions_from[$state] && test -n $match_anything_transitions_from[$state]
|
||||
set --local index (contains --index -- $state $match_anything_transitions_from)
|
||||
set index (contains --index -- $state $match_anything_transitions_from)
|
||||
set state $match_anything_transitions_to[$index]
|
||||
set word_index (math $word_index + 1)
|
||||
continue
|
||||
|
@ -80,8 +87,8 @@ function _hyprpm
|
|||
end
|
||||
|
||||
if set --query literal_transitions[$state] && test -n $literal_transitions[$state]
|
||||
set --local --erase inputs
|
||||
set --local --erase tos
|
||||
set --erase inputs
|
||||
set --erase tos
|
||||
eval $literal_transitions[$state]
|
||||
for literal_id in $inputs
|
||||
if test -n $descriptions[$literal_id]
|
||||
|
@ -92,14 +99,14 @@ function _hyprpm
|
|||
end
|
||||
end
|
||||
|
||||
set command_states 4
|
||||
set command_ids 1
|
||||
set command_states 4 3
|
||||
set command_ids 1 2
|
||||
if contains $state $command_states
|
||||
set --local index (contains --index $state $command_states)
|
||||
set --local function_id $command_ids[$index]
|
||||
set --local function_name _hyprpm_$function_id
|
||||
set --local --erase inputs
|
||||
set --local --erase tos
|
||||
set index (contains --index $state $command_states)
|
||||
set function_id $command_ids[$index]
|
||||
set function_name _hyprpm_$function_id
|
||||
set --erase inputs
|
||||
set --erase tos
|
||||
$function_name "$COMP_WORDS[$COMP_CWORD]"
|
||||
end
|
||||
|
||||
|
|
|
@ -5,10 +5,11 @@ hyprpm [<FLAGS>]... <ARGUMENT>
|
|||
| (--help | -h) "Show help menu"
|
||||
| (--verbose | -v) "Enable too much loggin"
|
||||
| (--force | -f) "Force an operation ignoring checks (e.g. update -f)"
|
||||
| (--no-shallow | -s) "Disable shallow cloning of Hyprland sources"
|
||||
;
|
||||
|
||||
<ARGUMENT> ::= (add) "Install a new plugin repository from git"
|
||||
| (remove) "Remove a plugin repository"
|
||||
| (remove <PLUGIN_REPOS>) "Remove a plugin repository"
|
||||
| (update) "Check and update all plugins if needed"
|
||||
| (list) "List all installed plugins"
|
||||
| (enable <PLUGINS>) "Load a plugin"
|
||||
|
@ -17,3 +18,4 @@ hyprpm [<FLAGS>]... <ARGUMENT>
|
|||
;
|
||||
|
||||
<PLUGINS> ::= {{{ hyprpm list | awk '/Plugin/{print $4}' }}};
|
||||
<PLUGIN_REPOS> ::= {{{ hyprpm list | awk '/Repository/{print $4}' | sed 's/:$//' }}};
|
||||
|
|
|
@ -4,34 +4,40 @@ _hyprpm_cmd_0 () {
|
|||
hyprpm list | awk '/Plugin/{print $4}'
|
||||
}
|
||||
|
||||
_hyprpm_cmd_1 () {
|
||||
hyprpm list | awk '/Repository/{print $4}' | sed 's/:$//'
|
||||
}
|
||||
|
||||
_hyprpm () {
|
||||
local -a literals=("-n" "::=" "list" "disable" "--help" "update" "add" "--verbose" "-v" "--force" "remove" "enable" "--notify" "-h" "reload" "-f")
|
||||
local -a literals=("--no-shallow" "-n" "::=" "disable" "list" "--help" "update" "add" "--verbose" "-v" "--force" "-s" "remove" "enable" "--notify" "-h" "reload" "-f")
|
||||
|
||||
local -A descriptions
|
||||
descriptions[1]="Send a hyprland notification for important events (e.g. load fail)"
|
||||
descriptions[3]="List all installed plugins"
|
||||
descriptions[1]="Disable shallow cloning of Hyprland sources"
|
||||
descriptions[2]="Send a hyprland notification for important events (e.g. load fail)"
|
||||
descriptions[4]="Unload a plugin"
|
||||
descriptions[5]="Show help menu"
|
||||
descriptions[6]="Check and update all plugins if needed"
|
||||
descriptions[7]="Install a new plugin repository from git"
|
||||
descriptions[8]="Enable too much loggin"
|
||||
descriptions[5]="List all installed plugins"
|
||||
descriptions[6]="Show help menu"
|
||||
descriptions[7]="Check and update all plugins if needed"
|
||||
descriptions[8]="Install a new plugin repository from git"
|
||||
descriptions[9]="Enable too much loggin"
|
||||
descriptions[10]="Force an operation ignoring checks (e.g. update -f)"
|
||||
descriptions[11]="Remove a plugin repository"
|
||||
descriptions[12]="Load a plugin"
|
||||
descriptions[13]="Send a hyprland notification for important events (e.g. load fail)"
|
||||
descriptions[14]="Show help menu"
|
||||
descriptions[15]="Reload all plugins"
|
||||
descriptions[16]="Force an operation ignoring checks (e.g. update -f)"
|
||||
descriptions[10]="Enable too much loggin"
|
||||
descriptions[11]="Force an operation ignoring checks (e.g. update -f)"
|
||||
descriptions[12]="Disable shallow cloning of Hyprland sources"
|
||||
descriptions[13]="Remove a plugin repository"
|
||||
descriptions[14]="Load a plugin"
|
||||
descriptions[15]="Send a hyprland notification for important events (e.g. load fail)"
|
||||
descriptions[16]="Show help menu"
|
||||
descriptions[17]="Reload all plugins"
|
||||
descriptions[18]="Force an operation ignoring checks (e.g. update -f)"
|
||||
|
||||
local -A literal_transitions
|
||||
literal_transitions[1]="([10]=7 [3]=3 [8]=7 [9]=7 [5]=7 [11]=3 [12]=4 [6]=3 [14]=7 [4]=4 [15]=3 [16]=7 [7]=3)"
|
||||
literal_transitions[2]="([11]=3 [12]=4 [4]=4 [3]=3 [15]=3 [6]=3 [7]=3)"
|
||||
literal_transitions[5]="([2]=6)"
|
||||
literal_transitions[6]="([1]=7 [13]=7)"
|
||||
literal_transitions[1]="([1]=8 [4]=4 [5]=5 [9]=8 [10]=8 [7]=5 [8]=5 [12]=8 [6]=8 [11]=8 [13]=3 [14]=4 [16]=8 [17]=5 [18]=8)"
|
||||
literal_transitions[2]="([13]=3 [14]=4 [4]=4 [5]=5 [17]=5 [7]=5 [8]=5)"
|
||||
literal_transitions[6]="([3]=7)"
|
||||
literal_transitions[7]="([2]=8 [15]=8)"
|
||||
|
||||
local -A match_anything_transitions
|
||||
match_anything_transitions=([4]=3 [3]=5 [1]=2 [2]=2)
|
||||
match_anything_transitions=([2]=2 [5]=6 [4]=5 [3]=5 [1]=2)
|
||||
|
||||
declare -A subword_transitions
|
||||
|
||||
|
@ -91,7 +97,7 @@ _hyprpm () {
|
|||
fi
|
||||
done
|
||||
fi
|
||||
local -A commands=([4]=0)
|
||||
local -A commands=([4]=0 [3]=1)
|
||||
|
||||
if [[ -v "commands[$state]" ]]; then
|
||||
local command_id=${commands[$state]}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#include "DataState.hpp"
|
||||
#include <toml++/toml.hpp>
|
||||
#include <iostream>
|
||||
#include <print>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include "PluginManager.hpp"
|
||||
|
@ -8,7 +8,7 @@
|
|||
std::string DataState::getDataStatePath() {
|
||||
const auto HOME = getenv("HOME");
|
||||
if (!HOME) {
|
||||
std::cerr << "DataState: no $HOME\n";
|
||||
std::println(stderr, "DataState: no $HOME");
|
||||
throw std::runtime_error("no $HOME");
|
||||
return "";
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ void DataState::addNewPluginRepo(const SPluginRepository& repo) {
|
|||
{"rev", repo.rev}
|
||||
}}
|
||||
};
|
||||
for (auto& p : repo.plugins) {
|
||||
for (auto const& p : repo.plugins) {
|
||||
// copy .so to the good place
|
||||
if (std::filesystem::exists(p.filename))
|
||||
std::filesystem::copy_file(p.filename, PATH + "/" + p.name + ".so");
|
||||
|
|
|
@ -6,7 +6,7 @@ CManifest::CManifest(const eManifestType type, const std::string& path) {
|
|||
auto manifest = toml::parse_file(path);
|
||||
|
||||
if (type == MANIFEST_HYPRLOAD) {
|
||||
for (auto& [key, val] : manifest) {
|
||||
for (auto const& [key, val] : manifest) {
|
||||
if (key.str().ends_with(".build"))
|
||||
continue;
|
||||
|
||||
|
@ -63,7 +63,7 @@ CManifest::CManifest(const eManifestType type, const std::string& path) {
|
|||
}
|
||||
}
|
||||
|
||||
for (auto& [key, val] : manifest) {
|
||||
for (auto const& [key, val] : manifest) {
|
||||
if (key.str() == "repository")
|
||||
continue;
|
||||
|
||||
|
|
|
@ -1,12 +1,15 @@
|
|||
#include "PluginManager.hpp"
|
||||
#include "../helpers/Colors.hpp"
|
||||
#include "../helpers/StringUtils.hpp"
|
||||
#include "../progress/CProgressBar.hpp"
|
||||
#include "Manifest.hpp"
|
||||
#include "DataState.hpp"
|
||||
|
||||
#include <cstdio>
|
||||
#include <iostream>
|
||||
#include <array>
|
||||
#include <filesystem>
|
||||
#include <print>
|
||||
#include <thread>
|
||||
#include <fstream>
|
||||
#include <algorithm>
|
||||
|
@ -31,6 +34,7 @@ static std::string execAndGet(std::string cmd) {
|
|||
if (!pipe)
|
||||
return "";
|
||||
|
||||
result.reserve(buffer.size());
|
||||
while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) {
|
||||
result += buffer.data();
|
||||
}
|
||||
|
@ -47,10 +51,10 @@ SHyprlandVersion CPluginManager::getHyprlandVersion() {
|
|||
once = true;
|
||||
const auto HLVERCALL = execAndGet("hyprctl version");
|
||||
if (m_bVerbose)
|
||||
std::cout << Colors::BLUE << "[v] " << Colors::RESET << "version returned: " << HLVERCALL << "\n";
|
||||
std::println("{}", verboseString("version returned: {}", HLVERCALL));
|
||||
|
||||
if (!HLVERCALL.contains("Tag:")) {
|
||||
std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " You don't seem to be running Hyprland.";
|
||||
std::println(stderr, "\n{}", failureString("You don't seem to be running Hyprland."));
|
||||
return SHyprlandVersion{};
|
||||
}
|
||||
|
||||
|
@ -76,7 +80,7 @@ SHyprlandVersion CPluginManager::getHyprlandVersion() {
|
|||
} catch (...) { ; }
|
||||
|
||||
if (m_bVerbose)
|
||||
std::cout << Colors::BLUE << "[v] " << Colors::RESET << "parsed commit " << hlcommit << " at branch " << hlbranch << " on " << hldate << ", commits " << commits << "\n";
|
||||
std::println("{}", verboseString("parsed commit {} at branch {} on {}, commits {}", hlcommit, hlbranch, hldate, commits));
|
||||
|
||||
ver = SHyprlandVersion{hlbranch, hlcommit, hldate, commits};
|
||||
return ver;
|
||||
|
@ -102,20 +106,21 @@ bool CPluginManager::addNewPluginRepo(const std::string& url, const std::string&
|
|||
const auto HLVER = getHyprlandVersion();
|
||||
|
||||
if (!hasDeps()) {
|
||||
std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " Could not clone the plugin repository. Dependencies not satisfied. Hyprpm requires: cmake, meson, cpio\n";
|
||||
std::println(stderr, "\n{}", failureString("Could not clone the plugin repository. Dependencies not satisfied. Hyprpm requires: cmake, meson, cpio"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (DataState::pluginRepoExists(url)) {
|
||||
std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " Could not clone the plugin repository. Repository already installed.\n";
|
||||
std::println(stderr, "\n{}", failureString("Could not clone the plugin repository. Repository already installed."));
|
||||
return false;
|
||||
}
|
||||
|
||||
auto GLOBALSTATE = DataState::getGlobalState();
|
||||
if (!GLOBALSTATE.dontWarnInstall) {
|
||||
std::cout << Colors::YELLOW << "!" << Colors::RED << " Disclaimer:\n " << Colors::RESET
|
||||
<< "plugins, especially not official, have no guarantee of stability, availablity or security.\n Run them at your own risk.\n "
|
||||
<< "This message will not appear again.\n";
|
||||
std::println("{}!{} Disclaimer: {}", Colors::YELLOW, Colors::RED, Colors::RESET);
|
||||
std::println("plugins, especially not official, have no guarantee of stability, availablity or security.\n"
|
||||
"Run them at your own risk.\n"
|
||||
"This message will not appear again.");
|
||||
GLOBALSTATE.dontWarnInstall = true;
|
||||
DataState::updateGlobalState(GLOBALSTATE);
|
||||
}
|
||||
|
@ -129,7 +134,7 @@ bool CPluginManager::addNewPluginRepo(const std::string& url, const std::string&
|
|||
std::getline(std::cin, input);
|
||||
|
||||
if (input.size() > 0 && input[0] != 'Y' && input[0] != 'y') {
|
||||
std::cout << "Aborting.\n";
|
||||
std::println(stderr, "Aborting.");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -144,7 +149,7 @@ bool CPluginManager::addNewPluginRepo(const std::string& url, const std::string&
|
|||
std::filesystem::create_directory("/tmp/hyprpm");
|
||||
std::filesystem::permissions("/tmp/hyprpm", std::filesystem::perms::all, std::filesystem::perm_options::replace);
|
||||
} else if (!std::filesystem::is_directory("/tmp/hyprpm")) {
|
||||
std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " Could not prepare working dir for hyprpm\n";
|
||||
std::println(stderr, "\n{}", failureString("Could not prepare working dir for hyprpm"));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -153,60 +158,60 @@ bool CPluginManager::addNewPluginRepo(const std::string& url, const std::string&
|
|||
m_szWorkingPluginDirectory = "/tmp/hyprpm/" + USERNAME;
|
||||
|
||||
if (!createSafeDirectory(m_szWorkingPluginDirectory)) {
|
||||
std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " Could not prepare working dir for repo\n";
|
||||
std::println(stderr, "\n{}", failureString("Could not prepare working dir for repo"));
|
||||
return false;
|
||||
}
|
||||
|
||||
progress.printMessageAbove(std::string{Colors::RESET} + " → Cloning " + url);
|
||||
progress.printMessageAbove(infoString("Cloning {}", url));
|
||||
|
||||
std::string ret = execAndGet("cd /tmp/hyprpm && git clone --recursive " + url + " " + USERNAME);
|
||||
|
||||
if (!std::filesystem::exists(m_szWorkingPluginDirectory + "/.git")) {
|
||||
std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " Could not clone the plugin repository. shell returned:\n" << ret << "\n";
|
||||
std::println(stderr, "\n{}", failureString("Could not clone the plugin repository. shell returned:\n{}", ret));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!rev.empty()) {
|
||||
std::string ret = execAndGet("git -C " + m_szWorkingPluginDirectory + " reset --hard --recurse-submodules " + rev);
|
||||
if (ret.compare(0, 6, "fatal:") == 0) {
|
||||
std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " Could not check out revision " << rev << ". shell returned:\n" << ret << "\n";
|
||||
std::println(stderr, "\n{}", failureString("Could not check out revision {}. shell returned:\n{}", rev, ret));
|
||||
return false;
|
||||
}
|
||||
ret = execAndGet("git -C " + m_szWorkingPluginDirectory + " submodule update --init");
|
||||
if (m_bVerbose)
|
||||
std::cout << Colors::BLUE << "[v] " << Colors::RESET << "git submodule update --init returned: " << ret << "\n";
|
||||
std::println("{}", verboseString("git submodule update --init returned: {}", ret));
|
||||
}
|
||||
|
||||
progress.m_iSteps = 1;
|
||||
progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " cloned");
|
||||
progress.printMessageAbove(successString("cloned"));
|
||||
progress.m_szCurrentMessage = "Reading the manifest";
|
||||
progress.print();
|
||||
|
||||
std::unique_ptr<CManifest> pManifest;
|
||||
|
||||
if (std::filesystem::exists(m_szWorkingPluginDirectory + "/hyprpm.toml")) {
|
||||
progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " found hyprpm manifest");
|
||||
progress.printMessageAbove(successString("found hyprpm manifest"));
|
||||
pManifest = std::make_unique<CManifest>(MANIFEST_HYPRPM, m_szWorkingPluginDirectory + "/hyprpm.toml");
|
||||
} else if (std::filesystem::exists(m_szWorkingPluginDirectory + "/hyprload.toml")) {
|
||||
progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " found hyprload manifest");
|
||||
progress.printMessageAbove(successString("found hyprload manifest"));
|
||||
pManifest = std::make_unique<CManifest>(MANIFEST_HYPRLOAD, m_szWorkingPluginDirectory + "/hyprload.toml");
|
||||
}
|
||||
|
||||
if (!pManifest) {
|
||||
std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " The provided plugin repository does not have a valid manifest\n";
|
||||
std::println(stderr, "\n{}", failureString("The provided plugin repository does not have a valid manifest"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!pManifest->m_bGood) {
|
||||
std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " The provided plugin repository has a corrupted manifest\n";
|
||||
std::println(stderr, "\n{}", failureString("The provided plugin repository has a corrupted manifest"));
|
||||
return false;
|
||||
}
|
||||
|
||||
progress.m_iSteps = 2;
|
||||
progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " parsed manifest, found " + std::to_string(pManifest->m_vPlugins.size()) + " plugins:");
|
||||
for (auto& pl : pManifest->m_vPlugins) {
|
||||
std::string message = std::string{Colors::RESET} + " → " + pl.name + " by ";
|
||||
for (auto& a : pl.authors) {
|
||||
progress.printMessageAbove(successString("parsed manifest, found " + std::to_string(pManifest->m_vPlugins.size()) + " plugins:"));
|
||||
for (auto const& pl : pManifest->m_vPlugins) {
|
||||
std::string message = "→ " + pl.name + " by ";
|
||||
for (auto const& a : pl.authors) {
|
||||
message += a + ", ";
|
||||
}
|
||||
if (pl.authors.size() > 0) {
|
||||
|
@ -220,19 +225,19 @@ bool CPluginManager::addNewPluginRepo(const std::string& url, const std::string&
|
|||
if (!pManifest->m_sRepository.commitPins.empty()) {
|
||||
// check commit pins
|
||||
|
||||
progress.printMessageAbove(std::string{Colors::RESET} + " → Manifest has " + std::to_string(pManifest->m_sRepository.commitPins.size()) + " pins, checking");
|
||||
progress.printMessageAbove(infoString("Manifest has {} pins, checking", pManifest->m_sRepository.commitPins.size()));
|
||||
|
||||
for (auto& [hl, plugin] : pManifest->m_sRepository.commitPins) {
|
||||
for (auto const& [hl, plugin] : pManifest->m_sRepository.commitPins) {
|
||||
if (hl != HLVER.hash)
|
||||
continue;
|
||||
|
||||
progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " commit pin " + plugin + " matched hl, resetting");
|
||||
progress.printMessageAbove(successString("commit pin {} matched hl, resetting", plugin));
|
||||
|
||||
execAndGet("cd " + m_szWorkingPluginDirectory + " && git reset --hard --recurse-submodules " + plugin);
|
||||
|
||||
ret = execAndGet("git -C " + m_szWorkingPluginDirectory + " submodule update --init");
|
||||
if (m_bVerbose)
|
||||
std::cout << Colors::BLUE << "[v] " << Colors::RESET << "git submodule update --init returned: " << ret << "\n";
|
||||
std::println("{}", verboseString("git submodule update --init returned: {}", ret));
|
||||
|
||||
break;
|
||||
}
|
||||
|
@ -244,12 +249,12 @@ bool CPluginManager::addNewPluginRepo(const std::string& url, const std::string&
|
|||
const auto HEADERSSTATUS = headersValid();
|
||||
|
||||
if (HEADERSSTATUS != HEADERS_OK) {
|
||||
std::cerr << "\n" << headerError(HEADERSSTATUS);
|
||||
std::println("\n{}", headerError(HEADERSSTATUS));
|
||||
return false;
|
||||
}
|
||||
|
||||
progress.m_iSteps = 3;
|
||||
progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " Hyprland headers OK");
|
||||
progress.printMessageAbove(successString("Hyprland headers OK"));
|
||||
progress.m_szCurrentMessage = "Building plugin(s)";
|
||||
progress.print();
|
||||
|
||||
|
@ -257,35 +262,36 @@ bool CPluginManager::addNewPluginRepo(const std::string& url, const std::string&
|
|||
std::string out;
|
||||
|
||||
if (p.since > HLVER.commits && HLVER.commits >= 1 /* for --depth 1 clones, we can't check this. */) {
|
||||
progress.printMessageAbove(std::string{Colors::RED} + "✖" + Colors::RESET + " Not building " + p.name + ": your Hyprland version is too old.\n");
|
||||
progress.printMessageAbove(failureString("Not building {}: your Hyprland version is too old.\n", p.name));
|
||||
p.failed = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
progress.printMessageAbove(std::string{Colors::RESET} + " → Building " + p.name);
|
||||
progress.printMessageAbove(infoString("Building {}", p.name));
|
||||
|
||||
for (auto& bs : p.buildSteps) {
|
||||
std::string cmd = std::format("cd {} && PKG_CONFIG_PATH=\"{}/share/pkgconfig\" {}", m_szWorkingPluginDirectory, DataState::getHeadersPath(), bs);
|
||||
for (auto const& bs : p.buildSteps) {
|
||||
const std::string& cmd = std::format("cd {} && PKG_CONFIG_PATH=\"{}/share/pkgconfig\" {}", m_szWorkingPluginDirectory, DataState::getHeadersPath(), bs);
|
||||
out += " -> " + cmd + "\n" + execAndGet(cmd) + "\n";
|
||||
}
|
||||
|
||||
if (m_bVerbose)
|
||||
std::cout << Colors::BLUE << "[v] " << Colors::RESET << "shell returned: " << out << "\n";
|
||||
std::println("{}", verboseString("shell returned: " + out));
|
||||
|
||||
if (!std::filesystem::exists(m_szWorkingPluginDirectory + "/" + p.output)) {
|
||||
progress.printMessageAbove(std::string{Colors::RED} + "✖" + Colors::RESET + " Plugin " + p.name + " failed to build.\n" +
|
||||
" This likely means that the plugin is either outdated, not yet available for your version, or broken.\n If you are on -git, update "
|
||||
"first.\n Try re-running with -v to see "
|
||||
"more verbose output.\n");
|
||||
progress.printMessageAbove(failureString("Plugin {} failed to build.\n"
|
||||
" This likely means that the plugin is either outdated, not yet available for your version, or broken.\n"
|
||||
" If you are on -git, update first\n"
|
||||
" Try re-running with -v to see more verbose output.\n",
|
||||
p.name));
|
||||
|
||||
p.failed = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " built " + p.name + " into " + p.output);
|
||||
progress.printMessageAbove(successString("built {} into {}", p.name, p.output));
|
||||
}
|
||||
|
||||
progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " all plugins built");
|
||||
progress.printMessageAbove(successString("all plugins built"));
|
||||
progress.m_iSteps = 4;
|
||||
progress.m_szCurrentMessage = "Installing repository";
|
||||
progress.print();
|
||||
|
@ -299,18 +305,18 @@ bool CPluginManager::addNewPluginRepo(const std::string& url, const std::string&
|
|||
repo.url = url;
|
||||
repo.rev = rev;
|
||||
repo.hash = repohash;
|
||||
for (auto& p : pManifest->m_vPlugins) {
|
||||
for (auto const& p : pManifest->m_vPlugins) {
|
||||
repo.plugins.push_back(SPlugin{p.name, m_szWorkingPluginDirectory + "/" + p.output, false, p.failed});
|
||||
}
|
||||
DataState::addNewPluginRepo(repo);
|
||||
|
||||
progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " installed repository");
|
||||
progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " you can now enable the plugin(s) with hyprpm enable");
|
||||
progress.printMessageAbove(successString("installed repository"));
|
||||
progress.printMessageAbove(successString("you can now enable the plugin(s) with hyprpm enable"));
|
||||
progress.m_iSteps = 5;
|
||||
progress.m_szCurrentMessage = "Done!";
|
||||
progress.print();
|
||||
|
||||
std::cout << "\n";
|
||||
std::print("\n");
|
||||
|
||||
// remove build files
|
||||
std::filesystem::remove_all(m_szWorkingPluginDirectory);
|
||||
|
@ -320,7 +326,7 @@ bool CPluginManager::addNewPluginRepo(const std::string& url, const std::string&
|
|||
|
||||
bool CPluginManager::removePluginRepo(const std::string& urlOrName) {
|
||||
if (!DataState::pluginRepoExists(urlOrName)) {
|
||||
std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " Could not remove the repository. Repository is not installed.\n";
|
||||
std::println(stderr, "\n{}", failureString("Could not remove the repository. Repository is not installed."));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -331,7 +337,7 @@ bool CPluginManager::removePluginRepo(const std::string& urlOrName) {
|
|||
std::getline(std::cin, input);
|
||||
|
||||
if (input.size() > 0 && input[0] != 'Y' && input[0] != 'y') {
|
||||
std::cout << "Aborting.\n";
|
||||
std::println("Aborting.");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -347,7 +353,7 @@ eHeadersErrors CPluginManager::headersValid() {
|
|||
return HEADERS_MISSING;
|
||||
|
||||
// find headers commit
|
||||
std::string cmd = std::format("PKG_CONFIG_PATH=\"{}/share/pkgconfig\" pkgconf --cflags --keep-system-cflags hyprland", DataState::getHeadersPath());
|
||||
const std::string& cmd = std::format("PKG_CONFIG_PATH=\"{}/share/pkgconfig\" pkgconf --cflags --keep-system-cflags hyprland", DataState::getHeadersPath());
|
||||
auto headers = execAndGet(cmd.c_str());
|
||||
|
||||
if (!headers.contains("-I/"))
|
||||
|
@ -355,7 +361,7 @@ eHeadersErrors CPluginManager::headersValid() {
|
|||
|
||||
headers.pop_back(); // pop newline
|
||||
|
||||
std::string verHeader = "";
|
||||
std::string verHeader;
|
||||
|
||||
while (!headers.empty()) {
|
||||
const auto PATH = headers.substr(0, headers.find(" -I/", 3));
|
||||
|
@ -406,7 +412,7 @@ bool CPluginManager::updateHeaders(bool force) {
|
|||
const auto HLVER = getHyprlandVersion();
|
||||
|
||||
if (!hasDeps()) {
|
||||
std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " Could not update. Dependencies not satisfied. Hyprpm requires: cmake, meson, cpio\n";
|
||||
std::println("\n{}", failureString("Could not update. Dependencies not satisfied. Hyprpm requires: cmake, meson, cpio"));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -416,7 +422,7 @@ bool CPluginManager::updateHeaders(bool force) {
|
|||
}
|
||||
|
||||
if (!force && headersValid() == HEADERS_OK) {
|
||||
std::cout << "\n" << std::string{Colors::GREEN} + "✔" + Colors::RESET + " Headers up to date.\n";
|
||||
std::println("\n{}", successString("Headers up to date."));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -430,74 +436,73 @@ bool CPluginManager::updateHeaders(bool force) {
|
|||
const auto WORKINGDIR = "/tmp/hyprpm/hyprland-" + USERNAME;
|
||||
|
||||
if (!createSafeDirectory(WORKINGDIR)) {
|
||||
std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " Could not prepare working dir for hl\n";
|
||||
std::println("\n{}", failureString("Could not prepare working dir for hl"));
|
||||
return false;
|
||||
}
|
||||
|
||||
progress.printMessageAbove(std::string{Colors::YELLOW} + "!" + Colors::RESET + " Cloning https://github.com/hyprwm/hyprland, this might take a moment.");
|
||||
progress.printMessageAbove(statusString("!", Colors::YELLOW, "Cloning https://github.com/hyprwm/Hyprland, this might take a moment."));
|
||||
|
||||
const bool bShallow = (HLVER.branch == "main" || HLVER.branch == "") && !m_bNoShallow;
|
||||
const bool bShallow = (HLVER.branch == "main") && !m_bNoShallow;
|
||||
|
||||
// let us give a bit of leg-room for shallowing
|
||||
// due to timezones, etc.
|
||||
const std::string SHALLOW_DATE =
|
||||
trim(HLVER.date).empty() ? "" : execAndGet("LC_TIME=\"en_US.UTF-8\" date --date='" + HLVER.date + " - 1 weeks' '+\%a \%b \%d \%H:\%M:\%S \%Y'");
|
||||
const std::string SHALLOW_DATE = trim(HLVER.date).empty() ? "" : execAndGet("LC_TIME=\"en_US.UTF-8\" date --date='" + HLVER.date + " - 1 weeks' '+%a %b %d %H:%M:%S %Y'");
|
||||
|
||||
if (m_bVerbose && bShallow)
|
||||
progress.printMessageAbove(std::string{Colors::BLUE} + "[v] " + Colors::RESET + "will shallow since: " + SHALLOW_DATE);
|
||||
progress.printMessageAbove(verboseString("will shallow since: {}", SHALLOW_DATE));
|
||||
|
||||
std::string ret =
|
||||
execAndGet("cd /tmp/hyprpm && git clone --recursive https://github.com/hyprwm/hyprland hyprland-" + USERNAME + (bShallow ? " --shallow-since='" + SHALLOW_DATE + "'" : ""));
|
||||
execAndGet("cd /tmp/hyprpm && git clone --recursive https://github.com/hyprwm/Hyprland hyprland-" + USERNAME + (bShallow ? " --shallow-since='" + SHALLOW_DATE + "'" : ""));
|
||||
|
||||
if (!std::filesystem::exists(WORKINGDIR)) {
|
||||
progress.printMessageAbove(std::string{Colors::RED} + "✖" + Colors::RESET + " Clone failed. Retrying without shallow.");
|
||||
progress.printMessageAbove(failureString("Clone failed. Retrying without shallow."));
|
||||
ret = execAndGet("cd /tmp/hyprpm && git clone --recursive https://github.com/hyprwm/hyprland hyprland-" + USERNAME);
|
||||
}
|
||||
|
||||
if (!std::filesystem::exists(WORKINGDIR + "/.git")) {
|
||||
std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " Could not clone the hyprland repository. shell returned:\n" << ret << "\n";
|
||||
std::println(stderr, "\n{}", failureString("Could not clone the Hyprland repository. shell returned:\n{}", ret));
|
||||
return false;
|
||||
}
|
||||
|
||||
progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " cloned");
|
||||
progress.printMessageAbove(successString("Hyprland cloned"));
|
||||
progress.m_iSteps = 2;
|
||||
progress.m_szCurrentMessage = "Checking out sources";
|
||||
progress.print();
|
||||
|
||||
if (m_bVerbose)
|
||||
progress.printMessageAbove(std::string{Colors::BLUE} + "[v] " + Colors::RESET + "will run: " + "cd " + WORKINGDIR + " && git checkout " + HLVER.hash + " 2>&1");
|
||||
progress.printMessageAbove(verboseString("will run: cd {} && git checkout {} 2>&1", WORKINGDIR, HLVER.hash));
|
||||
|
||||
ret = execAndGet("cd " + WORKINGDIR + " && git checkout " + HLVER.hash + " 2>&1");
|
||||
|
||||
if (ret.contains("fatal: unable to read tree")) {
|
||||
std::cerr << "\n"
|
||||
<< Colors::RED << "✖" << Colors::RESET
|
||||
<< " Could not checkout the running Hyprland commit. If you are on -git, try updating.\nYou can also try re-running hyprpm update with --no-shallow.\n";
|
||||
std::println(stderr, "\n{}",
|
||||
failureString("Could not checkout the running Hyprland commit. If you are on -git, try updating.\n"
|
||||
"You can also try re-running hyprpm update with --no-shallow."));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_bVerbose)
|
||||
progress.printMessageAbove(std::string{Colors::BLUE} + "[v] " + Colors::RESET + "git returned (co): " + ret);
|
||||
progress.printMessageAbove(verboseString("git returned (co): {}", ret));
|
||||
|
||||
ret = execAndGet("cd " + WORKINGDIR + " ; git rm subprojects/tracy ; git submodule update --init 2>&1 ; git reset --hard --recurse-submodules " + HLVER.hash);
|
||||
|
||||
if (m_bVerbose)
|
||||
progress.printMessageAbove(std::string{Colors::BLUE} + "[v] " + Colors::RESET + "git returned (rs): " + ret);
|
||||
progress.printMessageAbove(verboseString("git returned (rs): {}", ret));
|
||||
|
||||
progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " checked out to running ver");
|
||||
progress.printMessageAbove(successString("checked out to running ver"));
|
||||
progress.m_iSteps = 3;
|
||||
progress.m_szCurrentMessage = "Building Hyprland";
|
||||
progress.print();
|
||||
|
||||
progress.printMessageAbove(std::string{Colors::YELLOW} + "!" + Colors::RESET + " configuring Hyprland");
|
||||
progress.printMessageAbove(statusString("!", Colors::YELLOW, "configuring Hyprland"));
|
||||
|
||||
if (m_bVerbose)
|
||||
progress.printMessageAbove(std::string{Colors::BLUE} + "[v] " + Colors::RESET + "setting PREFIX for cmake to " + DataState::getHeadersPath());
|
||||
progress.printMessageAbove(verboseString("setting PREFIX for cmake to {}", DataState::getHeadersPath()));
|
||||
|
||||
ret = execAndGet(std::format("cd {} && cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:STRING=\"{}\" -S . -B ./build -G Ninja", WORKINGDIR,
|
||||
DataState::getHeadersPath()));
|
||||
if (m_bVerbose)
|
||||
progress.printMessageAbove(std::string{Colors::BLUE} + "[v] " + Colors::RESET + "cmake returned: " + ret);
|
||||
progress.printMessageAbove(verboseString("cmake returned: {}", ret));
|
||||
|
||||
if (ret.contains("CMake Error at")) {
|
||||
// missing deps, let the user know.
|
||||
|
@ -506,48 +511,46 @@ bool CPluginManager::updateHeaders(bool force) {
|
|||
missing = missing.substr(0, missing.find("-- Configuring incomplete"));
|
||||
missing = missing.substr(0, missing.find_last_of('\n'));
|
||||
|
||||
std::cerr << "\n"
|
||||
<< Colors::RED << "✖" << Colors::RESET << " Could not configure the hyprland source, cmake complained:\n"
|
||||
<< missing << "\n\nThis likely means that you are missing the above dependencies or they are out of date.\n";
|
||||
std::println(stderr, "\n{}",
|
||||
failureString("Could not configure the hyprland source, cmake complained:\n{}\n\n"
|
||||
"This likely means that you are missing the above dependencies or they are out of date.",
|
||||
missing));
|
||||
return false;
|
||||
}
|
||||
|
||||
progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " configured Hyprland");
|
||||
progress.printMessageAbove(successString("configured Hyprland"));
|
||||
progress.m_iSteps = 4;
|
||||
progress.m_szCurrentMessage = "Installing sources";
|
||||
progress.print();
|
||||
|
||||
std::string cmd =
|
||||
const std::string& cmd =
|
||||
std::format("sed -i -e \"s#PREFIX = /usr/local#PREFIX = {}#\" {}/Makefile && cd {} && make installheaders", DataState::getHeadersPath(), WORKINGDIR, WORKINGDIR);
|
||||
if (m_bVerbose)
|
||||
progress.printMessageAbove(std::string{Colors::BLUE} + "[v] " + Colors::RESET + "installation will run: " + cmd);
|
||||
progress.printMessageAbove(verboseString("installation will run: {}", cmd));
|
||||
|
||||
ret = execAndGet(cmd);
|
||||
|
||||
if (m_bVerbose)
|
||||
std::cout << Colors::BLUE << "[v] " << Colors::RESET << "installer returned: " << ret << "\n";
|
||||
std::println("{}", verboseString("installer returned: {}", ret));
|
||||
|
||||
// remove build files
|
||||
std::filesystem::remove_all(WORKINGDIR);
|
||||
|
||||
auto HEADERSVALID = headersValid();
|
||||
if (HEADERSVALID == HEADERS_OK) {
|
||||
progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " installed headers");
|
||||
progress.printMessageAbove(successString("installed headers"));
|
||||
progress.m_iSteps = 5;
|
||||
progress.m_szCurrentMessage = "Done!";
|
||||
progress.print();
|
||||
|
||||
std::cout << "\n";
|
||||
std::print("\n");
|
||||
} else {
|
||||
progress.printMessageAbove(std::string{Colors::RED} + "✖" + Colors::RESET + " failed to install headers with error code " + std::to_string((int)HEADERSVALID) + " (" +
|
||||
headerErrorShort(HEADERSVALID) + ")");
|
||||
progress.printMessageAbove(failureString("failed to install headers with error code {} ({})", (int)HEADERSVALID, headerErrorShort(HEADERSVALID)));
|
||||
progress.m_iSteps = 5;
|
||||
progress.m_szCurrentMessage = "Failed";
|
||||
progress.print();
|
||||
|
||||
std::cout << "\n";
|
||||
|
||||
std::cerr << "\n" << headerError(HEADERSVALID);
|
||||
std::print(stderr, "\n\n{}", headerError(HEADERSVALID));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -557,14 +560,14 @@ bool CPluginManager::updateHeaders(bool force) {
|
|||
|
||||
bool CPluginManager::updatePlugins(bool forceUpdateAll) {
|
||||
if (headersValid() != HEADERS_OK) {
|
||||
std::cout << "\n" << std::string{Colors::RED} + "✖" + Colors::RESET + " headers are not up-to-date, please run hyprpm update.\n";
|
||||
std::println("{}", failureString("headers are not up-to-date, please run hyprpm update."));
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto REPOS = DataState::getAllRepositories();
|
||||
|
||||
if (REPOS.size() < 1) {
|
||||
std::cout << "\n" << std::string{Colors::RED} + "✖" + Colors::RESET + " No repos to update.\n";
|
||||
std::println("{}", failureString("No repos to update."));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -579,32 +582,33 @@ bool CPluginManager::updatePlugins(bool forceUpdateAll) {
|
|||
const std::string USERNAME = getpwuid(getuid())->pw_name;
|
||||
m_szWorkingPluginDirectory = "/tmp/hyprpm/" + USERNAME;
|
||||
|
||||
for (auto& repo : REPOS) {
|
||||
for (auto const& repo : REPOS) {
|
||||
bool update = forceUpdateAll;
|
||||
|
||||
progress.m_iSteps++;
|
||||
progress.m_szCurrentMessage = "Updating " + repo.name;
|
||||
progress.print();
|
||||
|
||||
progress.printMessageAbove(std::string{Colors::RESET} + " → checking for updates for " + repo.name);
|
||||
progress.printMessageAbove(infoString("checking for updates for {}", repo.name));
|
||||
|
||||
createSafeDirectory(m_szWorkingPluginDirectory);
|
||||
|
||||
progress.printMessageAbove(std::string{Colors::RESET} + " → Cloning " + repo.url);
|
||||
progress.printMessageAbove(infoString("Cloning {}", repo.url));
|
||||
|
||||
std::string ret = execAndGet("cd /tmp/hyprpm && git clone --recursive " + repo.url + " " + USERNAME);
|
||||
|
||||
if (!std::filesystem::exists(m_szWorkingPluginDirectory + "/.git")) {
|
||||
std::cout << "\n" << std::string{Colors::RED} + "✖" + Colors::RESET + " could not clone repo: shell returned:\n" + ret;
|
||||
std::println("{}", failureString("could not clone repo: shell returned: {}", ret));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!repo.rev.empty()) {
|
||||
progress.printMessageAbove(std::string{Colors::RESET} + " → Plugin has revision set, resetting: " + repo.rev);
|
||||
progress.printMessageAbove(infoString("Plugin has revision set, resetting: {}", repo.rev));
|
||||
|
||||
std::string ret = execAndGet("git -C " + m_szWorkingPluginDirectory + " reset --hard --recurse-submodules " + repo.rev);
|
||||
if (ret.compare(0, 6, "fatal:") == 0) {
|
||||
std::cout << "\n" << std::string{Colors::RED} + "✖" + Colors::RESET + " could not check out revision " + repo.rev + ": shell returned:\n" + ret;
|
||||
std::println(stderr, "\n{}", failureString("could not check out revision {}: shell returned:\n{}", repo.rev, ret));
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -620,7 +624,7 @@ bool CPluginManager::updatePlugins(bool forceUpdateAll) {
|
|||
|
||||
if (!update) {
|
||||
std::filesystem::remove_all(m_szWorkingPluginDirectory);
|
||||
progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " repository " + repo.name + " is up-to-date.");
|
||||
progress.printMessageAbove(successString("repository {} is up-to-date.", repo.name));
|
||||
progress.m_iSteps++;
|
||||
progress.print();
|
||||
continue;
|
||||
|
@ -628,41 +632,41 @@ bool CPluginManager::updatePlugins(bool forceUpdateAll) {
|
|||
|
||||
// we need to update
|
||||
|
||||
progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " repository " + repo.name + " has updates.");
|
||||
progress.printMessageAbove(std::string{Colors::RESET} + " → Building " + repo.name);
|
||||
progress.printMessageAbove(successString("repository {} has updates.", repo.name));
|
||||
progress.printMessageAbove(infoString("Building {}", repo.name));
|
||||
progress.m_iSteps++;
|
||||
progress.print();
|
||||
|
||||
std::unique_ptr<CManifest> pManifest;
|
||||
|
||||
if (std::filesystem::exists(m_szWorkingPluginDirectory + "/hyprpm.toml")) {
|
||||
progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " found hyprpm manifest");
|
||||
progress.printMessageAbove(successString("found hyprpm manifest"));
|
||||
pManifest = std::make_unique<CManifest>(MANIFEST_HYPRPM, m_szWorkingPluginDirectory + "/hyprpm.toml");
|
||||
} else if (std::filesystem::exists(m_szWorkingPluginDirectory + "/hyprload.toml")) {
|
||||
progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " found hyprload manifest");
|
||||
progress.printMessageAbove(successString("found hyprload manifest"));
|
||||
pManifest = std::make_unique<CManifest>(MANIFEST_HYPRLOAD, m_szWorkingPluginDirectory + "/hyprload.toml");
|
||||
}
|
||||
|
||||
if (!pManifest) {
|
||||
std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " The provided plugin repository does not have a valid manifest\n";
|
||||
std::println(stderr, "\n{}", failureString("The provided plugin repository does not have a valid manifest"));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!pManifest->m_bGood) {
|
||||
std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " The provided plugin repository has a corrupted manifest\n";
|
||||
std::println(stderr, "\n{}", failureString("The provided plugin repository has a corrupted manifest"));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (repo.rev.empty() && !pManifest->m_sRepository.commitPins.empty()) {
|
||||
// check commit pins unless a revision is specified
|
||||
|
||||
progress.printMessageAbove(std::string{Colors::RESET} + " → Manifest has " + std::to_string(pManifest->m_sRepository.commitPins.size()) + " pins, checking");
|
||||
progress.printMessageAbove(infoString("Manifest has {} pins, checking", pManifest->m_sRepository.commitPins.size()));
|
||||
|
||||
for (auto& [hl, plugin] : pManifest->m_sRepository.commitPins) {
|
||||
for (auto const& [hl, plugin] : pManifest->m_sRepository.commitPins) {
|
||||
if (hl != HLVER.hash)
|
||||
continue;
|
||||
|
||||
progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " commit pin " + plugin + " matched hl, resetting");
|
||||
progress.printMessageAbove(successString("commit pin {} matched hl, resetting", plugin));
|
||||
|
||||
execAndGet("cd " + m_szWorkingPluginDirectory + " && git reset --hard --recurse-submodules " + plugin);
|
||||
}
|
||||
|
@ -672,32 +676,33 @@ bool CPluginManager::updatePlugins(bool forceUpdateAll) {
|
|||
std::string out;
|
||||
|
||||
if (p.since > HLVER.commits && HLVER.commits >= 1000 /* for shallow clones, we can't check this. 1000 is an arbitrary number I chose. */) {
|
||||
progress.printMessageAbove(std::string{Colors::RED} + "✖" + Colors::RESET + " Not building " + p.name + ": your Hyprland version is too old.\n");
|
||||
progress.printMessageAbove(failureString("Not building {}: your Hyprland version is too old.\n", p.name));
|
||||
p.failed = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
progress.printMessageAbove(std::string{Colors::RESET} + " → Building " + p.name);
|
||||
progress.printMessageAbove(infoString("Building {}", p.name));
|
||||
|
||||
for (auto& bs : p.buildSteps) {
|
||||
std::string cmd = std::format("cd {} && PKG_CONFIG_PATH=\"{}/share/pkgconfig\" {}", m_szWorkingPluginDirectory, DataState::getHeadersPath(), bs);
|
||||
for (auto const& bs : p.buildSteps) {
|
||||
const std::string& cmd = std::format("cd {} && PKG_CONFIG_PATH=\"{}/share/pkgconfig\" {}", m_szWorkingPluginDirectory, DataState::getHeadersPath(), bs);
|
||||
out += " -> " + cmd + "\n" + execAndGet(cmd) + "\n";
|
||||
}
|
||||
|
||||
if (m_bVerbose)
|
||||
std::cout << Colors::BLUE << "[v] " << Colors::RESET << "shell returned: " << out << "\n";
|
||||
std::println("{}", verboseString("shell returned: {}", out));
|
||||
|
||||
if (!std::filesystem::exists(m_szWorkingPluginDirectory + "/" + p.output)) {
|
||||
std::cerr << "\n"
|
||||
<< Colors::RED << "✖" << Colors::RESET << " Plugin " << p.name << " failed to build.\n"
|
||||
<< " This likely means that the plugin is either outdated, not yet available for your version, or broken.\n If you are on -git, update first.\n Try "
|
||||
"re-running with -v to see more verbose "
|
||||
"output.\n";
|
||||
std::println(stderr,
|
||||
"\n{}\n"
|
||||
" This likely means that the plugin is either outdated, not yet available for your version, or broken.\n"
|
||||
"If you are on -git, update first.\n"
|
||||
"Try re-running with -v to see more verbose output.",
|
||||
failureString("Plugin {} failed to build.", p.name));
|
||||
p.failed = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " built " + p.name + " into " + p.output);
|
||||
progress.printMessageAbove(successString("built {} into {}", p.name, p.output));
|
||||
}
|
||||
|
||||
// add repo toml to DataState
|
||||
|
@ -709,7 +714,7 @@ bool CPluginManager::updatePlugins(bool forceUpdateAll) {
|
|||
if (repohash.length() > 0)
|
||||
repohash.pop_back();
|
||||
newrepo.hash = repohash;
|
||||
for (auto& p : pManifest->m_vPlugins) {
|
||||
for (auto const& p : pManifest->m_vPlugins) {
|
||||
const auto OLDPLUGINIT = std::find_if(repo.plugins.begin(), repo.plugins.end(), [&](const auto& other) { return other.name == p.name; });
|
||||
newrepo.plugins.push_back(SPlugin{p.name, m_szWorkingPluginDirectory + "/" + p.output, OLDPLUGINIT != repo.plugins.end() ? OLDPLUGINIT->enabled : false});
|
||||
}
|
||||
|
@ -718,7 +723,7 @@ bool CPluginManager::updatePlugins(bool forceUpdateAll) {
|
|||
|
||||
std::filesystem::remove_all(m_szWorkingPluginDirectory);
|
||||
|
||||
progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " updated " + repo.name);
|
||||
progress.printMessageAbove(successString("updated {}", repo.name));
|
||||
}
|
||||
|
||||
progress.m_iSteps++;
|
||||
|
@ -733,7 +738,7 @@ bool CPluginManager::updatePlugins(bool forceUpdateAll) {
|
|||
progress.m_szCurrentMessage = "Done!";
|
||||
progress.print();
|
||||
|
||||
std::cout << "\n";
|
||||
std::print("\n");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -741,27 +746,27 @@ bool CPluginManager::updatePlugins(bool forceUpdateAll) {
|
|||
bool CPluginManager::enablePlugin(const std::string& name) {
|
||||
bool ret = DataState::setPluginEnabled(name, true);
|
||||
if (ret)
|
||||
std::cout << Colors::GREEN << "✔" << Colors::RESET << " Enabled " << name << "\n";
|
||||
std::println("{}", successString("Enabled {}", name));
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool CPluginManager::disablePlugin(const std::string& name) {
|
||||
bool ret = DataState::setPluginEnabled(name, false);
|
||||
if (ret)
|
||||
std::cout << Colors::GREEN << "✔" << Colors::RESET << " Disabled " << name << "\n";
|
||||
std::println("{}", successString("Disabled {}", name));
|
||||
return ret;
|
||||
}
|
||||
|
||||
ePluginLoadStateReturn CPluginManager::ensurePluginsLoadState() {
|
||||
if (headersValid() != HEADERS_OK) {
|
||||
std::cerr << "\n" << std::string{Colors::RED} + "✖" + Colors::RESET + " headers are not up-to-date, please run hyprpm update.\n";
|
||||
std::println(stderr, "\n{}", failureString("headers are not up-to-date, please run hyprpm update."));
|
||||
return LOADSTATE_HEADERS_OUTDATED;
|
||||
}
|
||||
|
||||
const auto HOME = getenv("HOME");
|
||||
const auto HIS = getenv("HYPRLAND_INSTANCE_SIGNATURE");
|
||||
if (!HOME || !HIS) {
|
||||
std::cerr << "PluginManager: no $HOME or HIS\n";
|
||||
std::println(stderr, "PluginManager: no $HOME or HIS");
|
||||
return LOADSTATE_FAIL;
|
||||
}
|
||||
const auto HYPRPMPATH = DataState::getDataStatePath() + "/";
|
||||
|
@ -770,14 +775,14 @@ ePluginLoadStateReturn CPluginManager::ensurePluginsLoadState() {
|
|||
|
||||
std::vector<std::string> loadedPlugins;
|
||||
|
||||
std::cout << Colors::GREEN << "✔" << Colors::RESET << " Ensuring plugin load state\n";
|
||||
std::println("{}", successString("Ensuring plugin load state"));
|
||||
|
||||
// iterate line by line
|
||||
while (!pluginLines.empty()) {
|
||||
auto plLine = pluginLines.substr(0, pluginLines.find("\n"));
|
||||
auto plLine = pluginLines.substr(0, pluginLines.find('\n'));
|
||||
|
||||
if (pluginLines.find("\n") != std::string::npos)
|
||||
pluginLines = pluginLines.substr(pluginLines.find("\n") + 1);
|
||||
if (pluginLines.find('\n') != std::string::npos)
|
||||
pluginLines = pluginLines.substr(pluginLines.find('\n') + 1);
|
||||
else
|
||||
pluginLines = "";
|
||||
|
||||
|
@ -794,8 +799,8 @@ ePluginLoadStateReturn CPluginManager::ensurePluginsLoadState() {
|
|||
const auto REPOS = DataState::getAllRepositories();
|
||||
|
||||
auto enabled = [REPOS](const std::string& plugin) -> bool {
|
||||
for (auto& r : REPOS) {
|
||||
for (auto& p : r.plugins) {
|
||||
for (auto const& r : REPOS) {
|
||||
for (auto const& p : r.plugins) {
|
||||
if (p.name == plugin && p.enabled)
|
||||
return true;
|
||||
}
|
||||
|
@ -805,8 +810,8 @@ ePluginLoadStateReturn CPluginManager::ensurePluginsLoadState() {
|
|||
};
|
||||
|
||||
auto repoForName = [REPOS](const std::string& name) -> std::string {
|
||||
for (auto& r : REPOS) {
|
||||
for (auto& p : r.plugins) {
|
||||
for (auto const& r : REPOS) {
|
||||
for (auto const& p : r.plugins) {
|
||||
if (p.name == name)
|
||||
return r.name;
|
||||
}
|
||||
|
@ -816,17 +821,17 @@ ePluginLoadStateReturn CPluginManager::ensurePluginsLoadState() {
|
|||
};
|
||||
|
||||
// unload disabled plugins
|
||||
for (auto& p : loadedPlugins) {
|
||||
for (auto const& p : loadedPlugins) {
|
||||
if (!enabled(p)) {
|
||||
// unload
|
||||
loadUnloadPlugin(HYPRPMPATH + repoForName(p) + "/" + p + ".so", false);
|
||||
std::cout << Colors::GREEN << "✔" << Colors::RESET << " Unloaded " << p << "\n";
|
||||
std::println("{}", successString("Unloaded {}", p));
|
||||
}
|
||||
}
|
||||
|
||||
// load enabled plugins
|
||||
for (auto& r : REPOS) {
|
||||
for (auto& p : r.plugins) {
|
||||
for (auto const& r : REPOS) {
|
||||
for (auto const& p : r.plugins) {
|
||||
if (!p.enabled)
|
||||
continue;
|
||||
|
||||
|
@ -834,11 +839,11 @@ ePluginLoadStateReturn CPluginManager::ensurePluginsLoadState() {
|
|||
continue;
|
||||
|
||||
loadUnloadPlugin(HYPRPMPATH + repoForName(p.name) + "/" + p.filename, true);
|
||||
std::cout << Colors::GREEN << "✔" << Colors::RESET << " Loaded " << p.name << "\n";
|
||||
std::println("{}", successString("Loaded {}", p.name));
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << Colors::GREEN << "✔" << Colors::RESET << " Plugin load state ensured\n";
|
||||
std::println("{}", successString("Plugin load state ensured"));
|
||||
|
||||
return LOADSTATE_OK;
|
||||
}
|
||||
|
@ -855,17 +860,18 @@ bool CPluginManager::loadUnloadPlugin(const std::string& path, bool load) {
|
|||
void CPluginManager::listAllPlugins() {
|
||||
const auto REPOS = DataState::getAllRepositories();
|
||||
|
||||
for (auto& r : REPOS) {
|
||||
std::cout << std::string{Colors::RESET} + " → Repository " + r.name + ":\n";
|
||||
for (auto const& r : REPOS) {
|
||||
std::println("{}", infoString("Repository {}:", r.name));
|
||||
|
||||
for (auto& p : r.plugins) {
|
||||
|
||||
std::cout << std::string{Colors::RESET} + " │ Plugin " + p.name;
|
||||
for (auto const& p : r.plugins) {
|
||||
std::println(" │ Plugin {}", p.name);
|
||||
|
||||
if (!p.failed)
|
||||
std::cout << "\n └─ enabled: " << (p.enabled ? Colors::GREEN : Colors::RED) << (p.enabled ? "true" : "false") << Colors::RESET << "\n";
|
||||
std::println(" └─ enabled: {}", (p.enabled ? std::string{Colors::GREEN} + "true" : std::string{Colors::RED} + "false"));
|
||||
else
|
||||
std::cout << "\n └─ enabled: " << Colors::RED << "Plugin failed to build" << Colors::RESET << "\n";
|
||||
std::println(" └─ enabled: {}Plugin failed to build", Colors::RED);
|
||||
|
||||
std::println("{}", Colors::RESET);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -876,19 +882,19 @@ void CPluginManager::notify(const eNotifyIcons icon, uint32_t color, int duratio
|
|||
|
||||
std::string CPluginManager::headerError(const eHeadersErrors err) {
|
||||
switch (err) {
|
||||
case HEADERS_CORRUPTED: return std::string{Colors::RED} + "✖" + Colors::RESET + " Headers corrupted. Please run hyprpm update to fix those.\n";
|
||||
case HEADERS_MISMATCHED: return std::string{Colors::RED} + "✖" + Colors::RESET + " Headers version mismatch. Please run hyprpm update to fix those.\n";
|
||||
case HEADERS_NOT_HYPRLAND: return std::string{Colors::RED} + "✖" + Colors::RESET + " It doesn't seem you are running on hyprland.\n";
|
||||
case HEADERS_MISSING: return std::string{Colors::RED} + "✖" + Colors::RESET + " Headers missing. Please run hyprpm update to fix those.\n";
|
||||
case HEADERS_CORRUPTED: return failureString("Headers corrupted. Please run hyprpm update to fix those.\n");
|
||||
case HEADERS_MISMATCHED: return failureString("Headers version mismatch. Please run hyprpm update to fix those.\n");
|
||||
case HEADERS_NOT_HYPRLAND: return failureString("It doesn't seem you are running on hyprland.\n");
|
||||
case HEADERS_MISSING: return failureString("Headers missing. Please run hyprpm update to fix those.\n");
|
||||
case HEADERS_DUPLICATED: {
|
||||
return std::string{Colors::RED} + "✖" + Colors::RESET + " Headers duplicated!!! This is a very bad sign.\n" +
|
||||
" This could be due to e.g. installing hyprland manually while a system package of hyprland is also installed.\n" +
|
||||
" If the above doesn't apply, check your /usr/include and /usr/local/include directories\n and remove all the hyprland headers.\n";
|
||||
return failureString("Headers duplicated!!! This is a very bad sign.\n"
|
||||
"This could be due to e.g. installing hyprland manually while a system package of hyprland is also installed.\n"
|
||||
"If the above doesn't apply, check your /usr/include and /usr/local/include directories\n and remove all the hyprland headers.\n");
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
|
||||
return std::string{Colors::RED} + "✖" + Colors::RESET + " Unknown header error. Please run hyprpm update to fix those.\n";
|
||||
return failureString("Unknown header error. Please run hyprpm update to fix those.\n");
|
||||
}
|
||||
|
||||
std::string CPluginManager::headerErrorShort(const eHeadersErrors err) {
|
||||
|
@ -904,9 +910,9 @@ std::string CPluginManager::headerErrorShort(const eHeadersErrors err) {
|
|||
}
|
||||
|
||||
bool CPluginManager::hasDeps() {
|
||||
std::vector<std::string> deps = {"meson", "cpio", "cmake"};
|
||||
for (auto& d : deps) {
|
||||
if (!execAndGet("which " + d + " 2>&1").contains("/"))
|
||||
std::vector<std::string> deps = {"meson", "cpio", "cmake", "pkg-config"};
|
||||
for (auto const& d : deps) {
|
||||
if (!execAndGet("command -v " + d).contains("/"))
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
enum eHeadersErrors {
|
||||
HEADERS_OK = 0,
|
||||
|
@ -68,7 +69,7 @@ class CPluginManager {
|
|||
std::string headerError(const eHeadersErrors err);
|
||||
std::string headerErrorShort(const eHeadersErrors err);
|
||||
|
||||
std::string m_szWorkingPluginDirectory = "";
|
||||
std::string m_szWorkingPluginDirectory;
|
||||
};
|
||||
|
||||
inline std::unique_ptr<CPluginManager> g_pPluginManager;
|
||||
|
|
32
hyprpm/src/helpers/StringUtils.hpp
Normal file
|
@ -0,0 +1,32 @@
|
|||
#pragma once
|
||||
|
||||
#include <format>
|
||||
#include <string>
|
||||
#include "Colors.hpp"
|
||||
|
||||
template <typename... Args>
|
||||
std::string statusString(const std::string_view emoji, const std::string_view color, const std::string_view fmt, Args&&... args) {
|
||||
std::string ret = std::format("{}{}{} ", color, emoji, Colors::RESET);
|
||||
ret += std::vformat(fmt, std::make_format_args(args...));
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
std::string successString(const std::string_view fmt, Args&&... args) {
|
||||
return statusString("✔", Colors::GREEN, fmt, args...);
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
std::string failureString(const std::string_view fmt, Args&&... args) {
|
||||
return statusString("✖", Colors::RED, fmt, args...);
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
std::string verboseString(const std::string_view fmt, Args&&... args) {
|
||||
return statusString("[v]", Colors::BLUE, fmt, args...);
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
std::string infoString(const std::string_view fmt, Args&&... args) {
|
||||
return statusString("→", Colors::RESET, fmt, args...);
|
||||
}
|
|
@ -1,15 +1,16 @@
|
|||
#include "progress/CProgressBar.hpp"
|
||||
#include "helpers/Colors.hpp"
|
||||
#include "helpers/StringUtils.hpp"
|
||||
#include "core/PluginManager.hpp"
|
||||
#include "core/DataState.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <cstdio>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <print>
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
|
||||
const std::string HELP = R"#(┏ hyprpm, a Hyprland Plugin Manager
|
||||
constexpr std::string_view HELP = R"#(┏ hyprpm, a Hyprland Plugin Manager
|
||||
┃
|
||||
┣ add [url] [git rev] → Install a new plugin repository from git. Git revision
|
||||
┃ is optional, when set, commit locks are ignored.
|
||||
|
@ -37,7 +38,7 @@ int main(int argc, char** argv, char** envp) {
|
|||
}
|
||||
|
||||
if (ARGS.size() < 2) {
|
||||
std::cout << HELP;
|
||||
std::println(stderr, "{}", HELP);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -47,7 +48,7 @@ int main(int argc, char** argv, char** envp) {
|
|||
for (int i = 1; i < argc; ++i) {
|
||||
if (ARGS[i].starts_with("-")) {
|
||||
if (ARGS[i] == "--help" || ARGS[i] == "-h") {
|
||||
std::cout << HELP;
|
||||
std::println("{}", HELP);
|
||||
return 0;
|
||||
} else if (ARGS[i] == "--notify" || ARGS[i] == "-n") {
|
||||
notify = true;
|
||||
|
@ -57,9 +58,9 @@ int main(int argc, char** argv, char** envp) {
|
|||
noShallow = true;
|
||||
} else if (ARGS[i] == "--force" || ARGS[i] == "-f") {
|
||||
force = true;
|
||||
std::cout << Colors::RED << "!" << Colors::RESET << " Using --force, I hope you know what you are doing.\n";
|
||||
std::println("{}", statusString("!", Colors::RED, "Using --force, I hope you know what you are doing."));
|
||||
} else {
|
||||
std::cerr << "Unrecognized option " << ARGS[i] << "\n";
|
||||
std::println(stderr, "Unrecognized option {}", ARGS[i]);
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
|
@ -68,7 +69,7 @@ int main(int argc, char** argv, char** envp) {
|
|||
}
|
||||
|
||||
if (command.empty()) {
|
||||
std::cout << HELP;
|
||||
std::println(stderr, "{}", HELP);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -78,7 +79,7 @@ int main(int argc, char** argv, char** envp) {
|
|||
|
||||
if (command[0] == "add") {
|
||||
if (command.size() < 2) {
|
||||
std::cerr << Colors::RED << "✖" << Colors::RESET << " Not enough args for add.\n";
|
||||
std::println(stderr, "{}", failureString("Not enough args for add."));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -90,7 +91,7 @@ int main(int argc, char** argv, char** envp) {
|
|||
return g_pPluginManager->addNewPluginRepo(command[1], rev) ? 0 : 1;
|
||||
} else if (command[0] == "remove") {
|
||||
if (ARGS.size() < 2) {
|
||||
std::cerr << Colors::RED << "✖" << Colors::RESET << " Not enough args for remove.\n";
|
||||
std::println(stderr, "{}", failureString("Not enough args for remove."));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -116,12 +117,12 @@ int main(int argc, char** argv, char** envp) {
|
|||
g_pPluginManager->notify(ICON_ERROR, 0, 10000, "[hyprpm] Couldn't update headers");
|
||||
} else if (command[0] == "enable") {
|
||||
if (ARGS.size() < 2) {
|
||||
std::cerr << Colors::RED << "✖" << Colors::RESET << " Not enough args for enable.\n";
|
||||
std::println(stderr, "{}", failureString("Not enough args for enable."));
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!g_pPluginManager->enablePlugin(command[1])) {
|
||||
std::cerr << Colors::RED << "✖" << Colors::RESET << " Couldn't enable plugin (missing?)\n";
|
||||
std::println(stderr, "{}", failureString("Couldn't enable plugin (missing?)"));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -130,12 +131,12 @@ int main(int argc, char** argv, char** envp) {
|
|||
return 1;
|
||||
} else if (command[0] == "disable") {
|
||||
if (command.size() < 2) {
|
||||
std::cerr << Colors::RED << "✖" << Colors::RESET << " Not enough args for disable.\n";
|
||||
std::println(stderr, "{}", failureString("Not enough args for disable."));
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!g_pPluginManager->disablePlugin(command[1])) {
|
||||
std::cerr << Colors::RED << "✖" << Colors::RESET << " Couldn't disable plugin (missing?)\n";
|
||||
std::println(stderr, "{}", failureString("Couldn't disable plugin (missing?)"));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -160,7 +161,7 @@ int main(int argc, char** argv, char** envp) {
|
|||
} else if (command[0] == "list") {
|
||||
g_pPluginManager->listAllPlugins();
|
||||
} else {
|
||||
std::cout << HELP;
|
||||
std::println(stderr, "{}", HELP);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,15 +1,31 @@
|
|||
globber = run_command('sh', '-c', 'find . -name "*.cpp" | sort', check: true)
|
||||
src = globber.stdout().strip().split('\n')
|
||||
|
||||
executable('hyprpm', src,
|
||||
executable(
|
||||
'hyprpm',
|
||||
src,
|
||||
dependencies: [
|
||||
dependency('hyprutils', version: '>= 0.1.1'),
|
||||
dependency('threads'),
|
||||
dependency('tomlplusplus')
|
||||
dependency('tomlplusplus'),
|
||||
],
|
||||
install : true
|
||||
install: true,
|
||||
)
|
||||
|
||||
install_data('../hyprpm.bash', install_dir: join_paths(get_option('datadir'), 'bash-completion/completions'), install_tag: 'runtime', rename: 'hyprpm')
|
||||
install_data('../hyprpm.fish', install_dir: join_paths(get_option('datadir'), 'fish/vendor_completions.d'), install_tag: 'runtime')
|
||||
install_data('../hyprpm.zsh', install_dir: join_paths(get_option('datadir'), 'zsh/site-functions'), install_tag: 'runtime', rename: '_hyprpm')
|
||||
install_data(
|
||||
'../hyprpm.bash',
|
||||
install_dir: join_paths(get_option('datadir'), 'bash-completion/completions'),
|
||||
install_tag: 'runtime',
|
||||
rename: 'hyprpm',
|
||||
)
|
||||
install_data(
|
||||
'../hyprpm.fish',
|
||||
install_dir: join_paths(get_option('datadir'), 'fish/vendor_completions.d'),
|
||||
install_tag: 'runtime',
|
||||
)
|
||||
install_data(
|
||||
'../hyprpm.zsh',
|
||||
install_dir: join_paths(get_option('datadir'), 'zsh/site-functions'),
|
||||
install_tag: 'runtime',
|
||||
rename: '_hyprpm',
|
||||
)
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
#include "CProgressBar.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <sys/ioctl.h>
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <format>
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <print>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
@ -16,11 +16,12 @@ void CProgressBar::printMessageAbove(const std::string& msg) {
|
|||
ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
|
||||
|
||||
std::string spaces;
|
||||
spaces.reserve(w.ws_col);
|
||||
for (size_t i = 0; i < w.ws_col; ++i) {
|
||||
spaces += ' ';
|
||||
}
|
||||
|
||||
std::cout << "\r" << spaces << "\r" << msg << "\n";
|
||||
std::println("\r{}\r{}", spaces, msg);
|
||||
print();
|
||||
}
|
||||
|
||||
|
@ -29,15 +30,16 @@ void CProgressBar::print() {
|
|||
ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
|
||||
|
||||
if (m_bFirstPrint)
|
||||
std::cout << "\n";
|
||||
std::print("\n");
|
||||
m_bFirstPrint = false;
|
||||
|
||||
std::string spaces;
|
||||
spaces.reserve(w.ws_col);
|
||||
for (size_t i = 0; i < w.ws_col; ++i) {
|
||||
spaces += ' ';
|
||||
}
|
||||
|
||||
std::cout << "\r" << spaces << "\r";
|
||||
std::print("\r{}\r", spaces);
|
||||
|
||||
std::string message = "";
|
||||
|
||||
|
@ -74,7 +76,7 @@ void CProgressBar::print() {
|
|||
message += " " + std::format("{} / {}", m_iSteps, m_iMaxSteps) + " ";
|
||||
|
||||
// draw message
|
||||
std::cout << message + " " + m_szCurrentMessage;
|
||||
std::print("{} {}", message, m_szCurrentMessage);
|
||||
|
||||
std::fflush(stdout);
|
||||
}
|
38
meson.build
|
@ -1,13 +1,17 @@
|
|||
project('Hyprland', 'cpp', 'c',
|
||||
version : run_command('cat', join_paths(meson.source_root(), 'VERSION'), check: true).stdout().strip(),
|
||||
project(
|
||||
'Hyprland',
|
||||
'cpp',
|
||||
'c',
|
||||
version: run_command('cat', join_paths(meson.project_source_root(), 'VERSION'), check: true).stdout().strip(),
|
||||
default_options: [
|
||||
'warning_level=2',
|
||||
'default_library=static',
|
||||
'optimization=3',
|
||||
'buildtype=release',
|
||||
'debug=false',
|
||||
'cpp_std=c++23',
|
||||
])
|
||||
'cpp_std=c++26',
|
||||
],
|
||||
)
|
||||
|
||||
datarootdir = '-DDATAROOTDIR="' + get_option('prefix') / get_option('datadir') + '"'
|
||||
add_project_arguments(
|
||||
|
@ -16,16 +20,20 @@ add_project_arguments(
|
|||
'-Wno-unused-value',
|
||||
'-Wno-missing-field-initializers',
|
||||
'-Wno-narrowing',
|
||||
'-Wno-pointer-arith',
|
||||
datarootdir,
|
||||
'-Wno-pointer-arith', datarootdir,
|
||||
'-DHYPRLAND_VERSION="' + meson.project_version() + '"',
|
||||
],
|
||||
language: 'cpp')
|
||||
language: 'cpp',
|
||||
)
|
||||
|
||||
cpp_compiler = meson.get_compiler('cpp')
|
||||
if cpp_compiler.check_header('execinfo.h')
|
||||
add_project_arguments('-DHAS_EXECINFO', language: 'cpp')
|
||||
endif
|
||||
|
||||
aquamarine = dependency('aquamarine', version: '>=0.4.2')
|
||||
add_project_arguments(['-DAQUAMARINE_VERSION="@0@"'.format(aquamarine.version())], language: 'cpp')
|
||||
|
||||
xcb_dep = dependency('xcb', required: get_option('xwayland'))
|
||||
xcb_composite_dep = dependency('xcb-composite', required: get_option('xwayland'))
|
||||
xcb_errors_dep = dependency('xcb-errors', required: get_option('xwayland'))
|
||||
|
@ -34,9 +42,7 @@ xcb_render_dep = dependency('xcb-render', required: get_option('xwayland'))
|
|||
xcb_res_dep = dependency('xcb-res', required: get_option('xwayland'))
|
||||
xcb_xfixes_dep = dependency('xcb-xfixes', required: get_option('xwayland'))
|
||||
|
||||
cmake = import('cmake')
|
||||
udis = cmake.subproject('udis86')
|
||||
udis86 = udis.dependency('libudis86')
|
||||
gio_dep = dependency('gio-2.0', required: true)
|
||||
|
||||
if not xcb_dep.found()
|
||||
add_project_arguments('-DNO_XWAYLAND', language: 'cpp')
|
||||
|
@ -45,6 +51,7 @@ endif
|
|||
backtrace_dep = cpp_compiler.find_library('execinfo', required: false)
|
||||
epoll_dep = dependency('epoll-shim', required: false) # timerfd on BSDs
|
||||
|
||||
# Handle options
|
||||
if get_option('systemd').enabled()
|
||||
add_project_arguments('-DUSES_SYSTEMD', language: 'cpp')
|
||||
endif
|
||||
|
@ -57,14 +64,22 @@ if get_option('buildtype') == 'debug'
|
|||
add_project_arguments('-DHYPRLAND_DEBUG', language: 'cpp')
|
||||
endif
|
||||
|
||||
version_h = run_command('sh', '-c', 'scripts/generateVersion.sh', check: true)
|
||||
# Generate hyprland version and populate version.h
|
||||
run_command('sh', '-c', 'scripts/generateVersion.sh', check: true)
|
||||
|
||||
# Install headers
|
||||
globber = run_command('find', 'src', '-name', '*.h*', check: true)
|
||||
headers = globber.stdout().strip().split('\n')
|
||||
foreach file : headers
|
||||
install_headers(file, subdir: 'hyprland', preserve_path: true)
|
||||
endforeach
|
||||
|
||||
tracy = dependency('tracy', static: true, required: get_option('tracy_enable'))
|
||||
|
||||
if get_option('tracy_enable') and get_option('buildtype') != 'debugoptimized'
|
||||
warning('Profiling builds should set -- buildtype = debugoptimized')
|
||||
endif
|
||||
|
||||
subdir('protocols')
|
||||
subdir('src')
|
||||
subdir('hyprctl')
|
||||
|
@ -73,6 +88,7 @@ subdir('assets')
|
|||
subdir('example')
|
||||
subdir('docs')
|
||||
|
||||
# Generate hyprland.pc
|
||||
pkg_install_dir = join_paths(get_option('datadir'), 'pkgconfig')
|
||||
|
||||
import('pkgconfig').generate(
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
option('xwayland', type: 'feature', value: 'auto', description: 'Enable support for X11 applications')
|
||||
option('systemd', type: 'feature', value: 'auto', description: 'Enable systemd integration')
|
||||
option('legacy_renderer', type: 'feature', value: 'disabled', description: 'Enable legacy renderer')
|
||||
option('tracy_enable', type: 'boolean', value: false , description: 'Enable profiling')
|
||||
|
|
118
nix/default.nix
|
@ -1,43 +1,33 @@
|
|||
{
|
||||
lib,
|
||||
stdenv,
|
||||
stdenvAdapters,
|
||||
pkg-config,
|
||||
pkgconf,
|
||||
makeWrapper,
|
||||
cmake,
|
||||
meson,
|
||||
ninja,
|
||||
aquamarine,
|
||||
binutils,
|
||||
cairo,
|
||||
expat,
|
||||
fribidi,
|
||||
git,
|
||||
hwdata,
|
||||
hyprcursor,
|
||||
hyprland-protocols,
|
||||
hyprlang,
|
||||
hyprutils,
|
||||
hyprwayland-scanner,
|
||||
jq,
|
||||
libGL,
|
||||
libdatrie,
|
||||
libdisplay-info,
|
||||
libdrm,
|
||||
libexecinfo,
|
||||
libinput,
|
||||
libliftoff,
|
||||
libselinux,
|
||||
libsepol,
|
||||
libthai,
|
||||
libuuid,
|
||||
libxkbcommon,
|
||||
libuuid,
|
||||
mesa,
|
||||
pango,
|
||||
pciutils,
|
||||
pcre2,
|
||||
python3,
|
||||
seatd,
|
||||
systemd,
|
||||
tomlplusplus,
|
||||
udis86-hyprland,
|
||||
wayland,
|
||||
wayland-protocols,
|
||||
wayland-scanner,
|
||||
|
@ -50,25 +40,39 @@
|
|||
wrapRuntimeDeps ? true,
|
||||
version ? "git",
|
||||
commit,
|
||||
revCount,
|
||||
date,
|
||||
# deprecated flags
|
||||
enableNvidiaPatches ? false,
|
||||
nvidiaPatches ? false,
|
||||
hidpiXWayland ? false,
|
||||
}:
|
||||
assert lib.assertMsg (!nvidiaPatches) "The option `nvidiaPatches` has been removed.";
|
||||
assert lib.assertMsg (!enableNvidiaPatches) "The option `enableNvidiaPatches` has been removed.";
|
||||
assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been removed. Please refer https://wiki.hyprland.org/Configuring/XWayland";
|
||||
stdenv.mkDerivation {
|
||||
pname = "hyprland${lib.optionalString debug "-debug"}";
|
||||
}: let
|
||||
inherit (builtins) baseNameOf foldl';
|
||||
inherit (lib.asserts) assertMsg;
|
||||
inherit (lib.attrsets) mapAttrsToList;
|
||||
inherit (lib.lists) flatten concatLists optional optionals;
|
||||
inherit (lib.sources) cleanSourceWith cleanSource;
|
||||
inherit (lib.strings) hasSuffix makeBinPath optionalString mesonBool mesonEnable;
|
||||
|
||||
adapters = flatten [
|
||||
stdenvAdapters.useMoldLinker
|
||||
];
|
||||
|
||||
customStdenv = foldl' (acc: adapter: adapter acc) stdenv adapters;
|
||||
in
|
||||
assert assertMsg (!nvidiaPatches) "The option `nvidiaPatches` has been removed.";
|
||||
assert assertMsg (!enableNvidiaPatches) "The option `enableNvidiaPatches` has been removed.";
|
||||
assert assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been removed. Please refer https://wiki.hyprland.org/Configuring/XWayland";
|
||||
customStdenv.mkDerivation {
|
||||
pname = "hyprland${optionalString debug "-debug"}";
|
||||
inherit version;
|
||||
|
||||
src = lib.cleanSourceWith {
|
||||
filter = name: type: let
|
||||
src = cleanSourceWith {
|
||||
filter = name: _type: let
|
||||
baseName = baseNameOf (toString name);
|
||||
in
|
||||
! (lib.hasSuffix ".nix" baseName);
|
||||
src = lib.cleanSource ../.;
|
||||
! (hasSuffix ".nix" baseName);
|
||||
src = cleanSource ../.;
|
||||
};
|
||||
|
||||
postPatch = ''
|
||||
|
@ -79,20 +83,21 @@ assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been remov
|
|||
sed -i "s#@PREFIX@/##g" hyprland.pc.in
|
||||
'';
|
||||
|
||||
COMMITS = commit;
|
||||
COMMITS = revCount;
|
||||
DATE = date;
|
||||
DIRTY = lib.optionalString (commit == "") "dirty";
|
||||
DIRTY = optionalString (commit == "") "dirty";
|
||||
HASH = commit;
|
||||
|
||||
depsBuildBuild = [
|
||||
pkg-config
|
||||
];
|
||||
|
||||
nativeBuildInputs = [
|
||||
hyprwayland-scanner
|
||||
jq
|
||||
makeWrapper
|
||||
cmake
|
||||
meson
|
||||
ninja
|
||||
pkg-config
|
||||
python3 # for udis86
|
||||
wayland-scanner
|
||||
];
|
||||
|
||||
outputs = [
|
||||
|
@ -101,69 +106,66 @@ assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been remov
|
|||
"dev"
|
||||
];
|
||||
|
||||
buildInputs = lib.concatLists [
|
||||
buildInputs = concatLists [
|
||||
[
|
||||
aquamarine
|
||||
cairo
|
||||
expat
|
||||
fribidi
|
||||
git
|
||||
hwdata
|
||||
hyprcursor
|
||||
hyprland-protocols
|
||||
hyprlang
|
||||
hyprutils
|
||||
libdatrie
|
||||
libdisplay-info
|
||||
libdrm
|
||||
libGL
|
||||
libinput
|
||||
libliftoff
|
||||
libselinux
|
||||
libsepol
|
||||
libthai
|
||||
libuuid
|
||||
libxkbcommon
|
||||
mesa
|
||||
pango
|
||||
pciutils
|
||||
pcre2
|
||||
seatd
|
||||
tomlplusplus
|
||||
udis86-hyprland
|
||||
wayland
|
||||
wayland-protocols
|
||||
]
|
||||
(lib.optionals stdenv.hostPlatform.isMusl [libexecinfo])
|
||||
(lib.optionals enableXWayland [
|
||||
xorg.libxcb
|
||||
wayland-scanner
|
||||
xorg.libXcursor
|
||||
]
|
||||
(optionals customStdenv.hostPlatform.isMusl [libexecinfo])
|
||||
(optionals enableXWayland [
|
||||
xorg.libxcb
|
||||
xorg.libXdmcp
|
||||
xorg.xcbutil
|
||||
xorg.xcbutilerrors
|
||||
xorg.xcbutilrenderutil
|
||||
xorg.xcbutilwm
|
||||
xwayland
|
||||
])
|
||||
(lib.optionals withSystemd [systemd])
|
||||
(optional withSystemd systemd)
|
||||
];
|
||||
|
||||
cmakeBuildType =
|
||||
mesonBuildType =
|
||||
if debug
|
||||
then "Debug"
|
||||
else "RelWithDebInfo";
|
||||
then "debugoptimized"
|
||||
else "release";
|
||||
|
||||
# we want as much debug info as possible
|
||||
dontStrip = debug;
|
||||
|
||||
cmakeFlags = [
|
||||
(lib.cmakeBool "NO_XWAYLAND" (!enableXWayland))
|
||||
(lib.cmakeBool "LEGACY_RENDERER" legacyRenderer)
|
||||
(lib.cmakeBool "NO_SYSTEMD" (!withSystemd))
|
||||
mesonFlags = flatten [
|
||||
(mapAttrsToList mesonEnable {
|
||||
"xwayland" = enableXWayland;
|
||||
"legacy_renderer" = legacyRenderer;
|
||||
"systemd" = withSystemd;
|
||||
})
|
||||
(mapAttrsToList mesonBool {
|
||||
"b_pch" = false;
|
||||
"tracy_enable" = false;
|
||||
})
|
||||
];
|
||||
|
||||
postInstall = ''
|
||||
${lib.optionalString wrapRuntimeDeps ''
|
||||
${optionalString wrapRuntimeDeps ''
|
||||
wrapProgram $out/bin/Hyprland \
|
||||
--suffix PATH : ${lib.makeBinPath [
|
||||
--suffix PATH : ${makeBinPath [
|
||||
binutils
|
||||
pciutils
|
||||
pkgconf
|
||||
|
|
64
nix/formatter.nix
Normal file
|
@ -0,0 +1,64 @@
|
|||
{
|
||||
writeShellApplication,
|
||||
deadnix,
|
||||
statix,
|
||||
alejandra,
|
||||
llvmPackages_19,
|
||||
fd,
|
||||
}:
|
||||
writeShellApplication {
|
||||
name = "hyprland-treewide-formatter";
|
||||
runtimeInputs = [
|
||||
deadnix
|
||||
statix
|
||||
alejandra
|
||||
llvmPackages_19.clang-tools
|
||||
fd
|
||||
];
|
||||
text = ''
|
||||
# shellcheck disable=SC2148
|
||||
|
||||
# common excludes
|
||||
excludes="subprojects"
|
||||
|
||||
nix_format() {
|
||||
if [ "$*" = 0 ]; then
|
||||
fd '.*\.nix' . -E "$excludes" -x statix fix -- {} \;
|
||||
fd '.*\.nix' . -E "$excludes" -X deadnix -e -- {} \; -X alejandra {} \;
|
||||
elif [ -d "$1" ]; then
|
||||
fd '.*\.nix' "$1" -E "$excludes" -i -x statix fix -- {} \;
|
||||
fd '.*\.nix' "$1" -E "$excludes" -i -X deadnix -e -- {} \; -X alejandra {} \;
|
||||
else
|
||||
statix fix -- "$1"
|
||||
deadnix -e "$1"
|
||||
alejandra "$1"
|
||||
fi
|
||||
}
|
||||
|
||||
cpp_format() {
|
||||
if [ "$*" = 0 ] || [ "$1" = "." ]; then
|
||||
fd '.*\.cpp' . -E "$excludes" | xargs clang-format --verbose -i
|
||||
elif [ -d "$1" ]; then
|
||||
fd '.*\.cpp' "$1" -E "$excludes" | xargs clang-format --verbose -i
|
||||
else
|
||||
clang-format --verbose -i "$1"
|
||||
fi
|
||||
}
|
||||
|
||||
for i in "$@"; do
|
||||
case ''${i##*.} in
|
||||
"nix")
|
||||
nix_format "$i"
|
||||
;;
|
||||
"cpp")
|
||||
cpp_format "$i"
|
||||
;;
|
||||
*)
|
||||
nix_format "$i"
|
||||
cpp_format "$i"
|
||||
;;
|
||||
esac
|
||||
|
||||
done
|
||||
'';
|
||||
}
|
|
@ -22,18 +22,21 @@ in {
|
|||
# Dependencies
|
||||
inputs.aquamarine.overlays.default
|
||||
inputs.hyprcursor.overlays.default
|
||||
inputs.hyprland-protocols.overlays.default
|
||||
inputs.hyprlang.overlays.default
|
||||
inputs.hyprutils.overlays.default
|
||||
inputs.hyprwayland-scanner.overlays.default
|
||||
self.overlays.udis86
|
||||
|
||||
# Hyprland packages themselves
|
||||
(final: prev: let
|
||||
(final: _prev: let
|
||||
date = mkDate (self.lastModifiedDate or "19700101");
|
||||
in {
|
||||
hyprland = final.callPackage ./default.nix {
|
||||
stdenv = final.gcc13Stdenv;
|
||||
stdenv = final.gcc14Stdenv;
|
||||
version = "${version}+date=${date}_${self.shortRev or "dirty"}";
|
||||
commit = self.rev or "";
|
||||
revCount = self.sourceInfo.revCount or "";
|
||||
inherit date;
|
||||
};
|
||||
hyprland-unwrapped = final.hyprland.override {wrapRuntimeDeps = false;};
|
||||
|
@ -62,4 +65,20 @@ in {
|
|||
hyprland-extras = lib.composeManyExtensions [
|
||||
inputs.xdph.overlays.xdg-desktop-portal-hyprland
|
||||
];
|
||||
|
||||
# udis86 from nixpkgs is too old, and also does not provide a .pc file
|
||||
# this version is the one used in the git submodule, and allows us to
|
||||
# fetch the source without '?submodules=1'
|
||||
udis86 = final: prev: {
|
||||
udis86-hyprland = prev.udis86.overrideAttrs (_self: _super: {
|
||||
src = final.fetchFromGitHub {
|
||||
owner = "canihavesomecoffee";
|
||||
repo = "udis86";
|
||||
rev = "5336633af70f3917760a6d441ff02d93477b0c86";
|
||||
hash = "sha256-HifdUQPGsKQKQprByeIznvRLONdOXeolOsU5nkwIv3g=";
|
||||
};
|
||||
|
||||
patches = [];
|
||||
});
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,76 +1,78 @@
|
|||
wayland_protos = dependency('wayland-protocols',
|
||||
wayland_protos = dependency(
|
||||
'wayland-protocols',
|
||||
version: '>=1.32',
|
||||
fallback: 'wayland-protocols',
|
||||
default_options: ['tests=false'],
|
||||
)
|
||||
|
||||
hyprland_protos = dependency('hyprland-protocols',
|
||||
version: '>=0.2',
|
||||
hyprland_protos = dependency(
|
||||
'hyprland-protocols',
|
||||
version: '>=0.4',
|
||||
fallback: 'hyprland-protocols',
|
||||
)
|
||||
|
||||
wl_protocol_dir = wayland_protos.get_variable('pkgdatadir')
|
||||
hl_protocol_dir = hyprland_protos.get_variable('pkgdatadir')
|
||||
wayland_protocol_dir = wayland_protos.get_variable('pkgdatadir')
|
||||
hyprland_protocol_dir = hyprland_protos.get_variable('pkgdatadir')
|
||||
|
||||
hyprwayland_scanner_dep = dependency('hyprwayland-scanner', version: '>=0.3.8', native: true)
|
||||
hyprwayland_scanner_dep = dependency('hyprwayland-scanner', version: '>=0.3.10', native: true)
|
||||
hyprwayland_scanner = find_program(
|
||||
hyprwayland_scanner_dep.get_variable('hyprwayland_scanner'),
|
||||
native: true,
|
||||
)
|
||||
|
||||
new_protocols = [
|
||||
['wlr-gamma-control-unstable-v1.xml'],
|
||||
['wlr-foreign-toplevel-management-unstable-v1.xml'],
|
||||
['wlr-output-power-management-unstable-v1.xml'],
|
||||
['input-method-unstable-v2.xml'],
|
||||
['virtual-keyboard-unstable-v1.xml'],
|
||||
['wlr-virtual-pointer-unstable-v1.xml'],
|
||||
['wlr-output-management-unstable-v1.xml'],
|
||||
['kde-server-decoration.xml'],
|
||||
['wlr-layer-shell-unstable-v1.xml'],
|
||||
['wayland-drm.xml'],
|
||||
['wlr-data-control-unstable-v1.xml'],
|
||||
['wlr-screencopy-unstable-v1.xml'],
|
||||
[hl_protocol_dir, 'protocols/hyprland-global-shortcuts-v1.xml'],
|
||||
[hl_protocol_dir, 'protocols/hyprland-toplevel-export-v1.xml'],
|
||||
[hl_protocol_dir, 'protocols/hyprland-focus-grab-v1.xml'],
|
||||
[wl_protocol_dir, 'staging/tearing-control/tearing-control-v1.xml'],
|
||||
[wl_protocol_dir, 'staging/fractional-scale/fractional-scale-v1.xml'],
|
||||
[wl_protocol_dir, 'unstable/xdg-output/xdg-output-unstable-v1.xml'],
|
||||
[wl_protocol_dir, 'staging/cursor-shape/cursor-shape-v1.xml'],
|
||||
[wl_protocol_dir, 'unstable/idle-inhibit/idle-inhibit-unstable-v1.xml'],
|
||||
[wl_protocol_dir, 'unstable/relative-pointer/relative-pointer-unstable-v1.xml'],
|
||||
[wl_protocol_dir, 'unstable/xdg-decoration/xdg-decoration-unstable-v1.xml'],
|
||||
[wl_protocol_dir, 'staging/alpha-modifier/alpha-modifier-v1.xml'],
|
||||
[wl_protocol_dir, 'staging/ext-foreign-toplevel-list/ext-foreign-toplevel-list-v1.xml'],
|
||||
[wl_protocol_dir, 'unstable/pointer-gestures/pointer-gestures-unstable-v1.xml'],
|
||||
[wl_protocol_dir, 'unstable/keyboard-shortcuts-inhibit/keyboard-shortcuts-inhibit-unstable-v1.xml'],
|
||||
[wl_protocol_dir, 'unstable/text-input/text-input-unstable-v3.xml'],
|
||||
[wl_protocol_dir, 'unstable/text-input/text-input-unstable-v1.xml'],
|
||||
[wl_protocol_dir, 'unstable/pointer-constraints/pointer-constraints-unstable-v1.xml'],
|
||||
[wl_protocol_dir, 'staging/xdg-activation/xdg-activation-v1.xml'],
|
||||
[wl_protocol_dir, 'staging/ext-idle-notify/ext-idle-notify-v1.xml'],
|
||||
[wl_protocol_dir, 'staging/ext-session-lock/ext-session-lock-v1.xml'],
|
||||
[wl_protocol_dir, 'stable/tablet/tablet-v2.xml'],
|
||||
[wl_protocol_dir, 'stable/presentation-time/presentation-time.xml'],
|
||||
[wl_protocol_dir, 'stable/xdg-shell/xdg-shell.xml'],
|
||||
[wl_protocol_dir, 'unstable/primary-selection/primary-selection-unstable-v1.xml'],
|
||||
[wl_protocol_dir, 'staging/xwayland-shell/xwayland-shell-v1.xml'],
|
||||
[wl_protocol_dir, 'stable/viewporter/viewporter.xml'],
|
||||
[wl_protocol_dir, 'stable/linux-dmabuf/linux-dmabuf-v1.xml'],
|
||||
[wl_protocol_dir, 'staging/drm-lease/drm-lease-v1.xml'],
|
||||
[wl_protocol_dir, 'staging/linux-drm-syncobj/linux-drm-syncobj-v1.xml'],
|
||||
protocols = [
|
||||
'wlr-gamma-control-unstable-v1.xml',
|
||||
'wlr-foreign-toplevel-management-unstable-v1.xml',
|
||||
'wlr-output-power-management-unstable-v1.xml',
|
||||
'input-method-unstable-v2.xml',
|
||||
'virtual-keyboard-unstable-v1.xml',
|
||||
'wlr-virtual-pointer-unstable-v1.xml',
|
||||
'wlr-output-management-unstable-v1.xml',
|
||||
'kde-server-decoration.xml',
|
||||
'wlr-layer-shell-unstable-v1.xml',
|
||||
'wayland-drm.xml',
|
||||
'wlr-data-control-unstable-v1.xml',
|
||||
'wlr-screencopy-unstable-v1.xml',
|
||||
hyprland_protocol_dir / 'protocols/hyprland-global-shortcuts-v1.xml',
|
||||
hyprland_protocol_dir / 'protocols/hyprland-toplevel-export-v1.xml',
|
||||
hyprland_protocol_dir / 'protocols/hyprland-focus-grab-v1.xml',
|
||||
hyprland_protocol_dir / 'protocols/hyprland-ctm-control-v1.xml',
|
||||
wayland_protocol_dir / 'staging/tearing-control/tearing-control-v1.xml',
|
||||
wayland_protocol_dir / 'staging/fractional-scale/fractional-scale-v1.xml',
|
||||
wayland_protocol_dir / 'unstable/xdg-output/xdg-output-unstable-v1.xml',
|
||||
wayland_protocol_dir / 'staging/cursor-shape/cursor-shape-v1.xml',
|
||||
wayland_protocol_dir / 'unstable/idle-inhibit/idle-inhibit-unstable-v1.xml',
|
||||
wayland_protocol_dir / 'unstable/relative-pointer/relative-pointer-unstable-v1.xml',
|
||||
wayland_protocol_dir / 'unstable/xdg-decoration/xdg-decoration-unstable-v1.xml',
|
||||
wayland_protocol_dir / 'staging/alpha-modifier/alpha-modifier-v1.xml',
|
||||
wayland_protocol_dir / 'staging/ext-foreign-toplevel-list/ext-foreign-toplevel-list-v1.xml',
|
||||
wayland_protocol_dir / 'unstable/pointer-gestures/pointer-gestures-unstable-v1.xml',
|
||||
wayland_protocol_dir / 'unstable/keyboard-shortcuts-inhibit/keyboard-shortcuts-inhibit-unstable-v1.xml',
|
||||
wayland_protocol_dir / 'unstable/text-input/text-input-unstable-v3.xml',
|
||||
wayland_protocol_dir / 'unstable/text-input/text-input-unstable-v1.xml',
|
||||
wayland_protocol_dir / 'unstable/pointer-constraints/pointer-constraints-unstable-v1.xml',
|
||||
wayland_protocol_dir / 'staging/xdg-activation/xdg-activation-v1.xml',
|
||||
wayland_protocol_dir / 'staging/ext-idle-notify/ext-idle-notify-v1.xml',
|
||||
wayland_protocol_dir / 'staging/ext-session-lock/ext-session-lock-v1.xml',
|
||||
wayland_protocol_dir / 'stable/tablet/tablet-v2.xml',
|
||||
wayland_protocol_dir / 'stable/presentation-time/presentation-time.xml',
|
||||
wayland_protocol_dir / 'stable/xdg-shell/xdg-shell.xml',
|
||||
wayland_protocol_dir / 'unstable/primary-selection/primary-selection-unstable-v1.xml',
|
||||
wayland_protocol_dir / 'staging/xwayland-shell/xwayland-shell-v1.xml',
|
||||
wayland_protocol_dir / 'stable/viewporter/viewporter.xml',
|
||||
wayland_protocol_dir / 'stable/linux-dmabuf/linux-dmabuf-v1.xml',
|
||||
wayland_protocol_dir / 'staging/drm-lease/drm-lease-v1.xml',
|
||||
wayland_protocol_dir / 'staging/linux-drm-syncobj/linux-drm-syncobj-v1.xml',
|
||||
wayland_protocol_dir / 'staging/xdg-dialog/xdg-dialog-v1.xml',
|
||||
wayland_protocol_dir / 'staging/single-pixel-buffer/single-pixel-buffer-v1.xml',
|
||||
wayland_protocol_dir / 'staging/security-context/security-context-v1.xml',
|
||||
]
|
||||
|
||||
wl_protos_src = []
|
||||
wl_protos_headers = []
|
||||
|
||||
new_wl_protos = []
|
||||
foreach p : new_protocols
|
||||
xml = join_paths(p)
|
||||
new_wl_protos += custom_target(
|
||||
xml.underscorify(),
|
||||
input: xml,
|
||||
wl_protocols = []
|
||||
foreach protocol : protocols
|
||||
wl_protocols += custom_target(
|
||||
protocol.underscorify(),
|
||||
input: protocol,
|
||||
install: true,
|
||||
install_dir: [false, join_paths(get_option('includedir'), 'hyprland/protocols')],
|
||||
output: ['@BASENAME@.cpp', '@BASENAME@.hpp'],
|
||||
|
@ -78,31 +80,26 @@ foreach p : new_protocols
|
|||
)
|
||||
endforeach
|
||||
|
||||
wayland_server_dep = dependency('wayland-server', version: '>=1.20.0')
|
||||
wayland_server_dir = wayland_server_dep.get_variable('pkgdatadir')
|
||||
# wayland.xml generation
|
||||
wayland_scanner = dependency('wayland-scanner')
|
||||
wayland_scanner_datadir = wayland_scanner.get_variable('pkgdatadir')
|
||||
|
||||
wl_server_protos = [
|
||||
wayland_server_dir / 'wayland.xml'
|
||||
]
|
||||
wl_server_protos_gen = []
|
||||
foreach p : wl_server_protos
|
||||
wl_server_protos_gen += custom_target(
|
||||
p.underscorify(),
|
||||
input: p,
|
||||
wayland_xml = wayland_scanner_datadir / 'wayland.xml'
|
||||
wayland_protocol = custom_target(
|
||||
wayland_xml.underscorify(),
|
||||
input: wayland_xml,
|
||||
install: true,
|
||||
install_dir: [false, join_paths(get_option('includedir'), 'hyprland/protocols')],
|
||||
output: ['@BASENAME@.cpp', '@BASENAME@.hpp'],
|
||||
command: [hyprwayland_scanner, '--wayland-enums', '@INPUT@', '@OUTDIR@'],
|
||||
)
|
||||
endforeach
|
||||
|
||||
lib_server_protos = static_library(
|
||||
'server_protos',
|
||||
wl_protos_src + wl_protos_headers + new_wl_protos + wl_server_protos_gen,
|
||||
dependencies: wayland_server_dep.partial_dependency(compile_args: true),
|
||||
wl_protocols + wayland_protocol,
|
||||
)
|
||||
|
||||
server_protos = declare_dependency(
|
||||
link_with: lib_server_protos,
|
||||
sources: wl_protos_headers + new_wl_protos,
|
||||
sources: wl_protocols + wayland_protocol,
|
||||
)
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
diff --git a/CMakeLists.txt b/CMakeLists.txt
|
||||
index f54cdf5d..ad7c3e73 100755
|
||||
index f26a5c3c..3dfef333 100644
|
||||
--- a/CMakeLists.txt
|
||||
+++ b/CMakeLists.txt
|
||||
@@ -130,6 +130,8 @@ if(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG)
|
||||
@@ -143,6 +143,8 @@ if(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG)
|
||||
message(STATUS "Enabling ASan")
|
||||
|
||||
target_link_libraries(Hyprland asan)
|
||||
|
|
|
@ -67,7 +67,7 @@ class CCompositor {
|
|||
std::vector<PHLWINDOWREF> m_vWindowsFadingOut;
|
||||
std::vector<PHLLSREF> m_vSurfacesFadingOut;
|
||||
|
||||
std::unordered_map<std::string, uint64_t> m_mMonitorIDMap;
|
||||
std::unordered_map<std::string, MONITORID> m_mMonitorIDMap;
|
||||
|
||||
void initServer(std::string socketName, int socketFd);
|
||||
void startCompositor();
|
||||
|
@ -91,10 +91,13 @@ class CCompositor {
|
|||
bool m_bNextIsUnsafe = false;
|
||||
CMonitor* m_pUnsafeOutput = nullptr; // fallback output for the unsafe state
|
||||
bool m_bIsShuttingDown = false;
|
||||
bool m_bFinalRequests = false;
|
||||
bool m_bDesktopEnvSet = false;
|
||||
bool m_bEnableXwayland = true;
|
||||
|
||||
// ------------------------------------------------- //
|
||||
|
||||
CMonitor* getMonitorFromID(const int&);
|
||||
CMonitor* getMonitorFromID(const MONITORID&);
|
||||
CMonitor* getMonitorFromName(const std::string&);
|
||||
CMonitor* getMonitorFromDesc(const std::string&);
|
||||
CMonitor* getMonitorFromCursor();
|
||||
|
@ -114,38 +117,38 @@ class CCompositor {
|
|||
PHLWINDOW getWindowFromHandle(uint32_t);
|
||||
bool isWorkspaceVisible(PHLWORKSPACE);
|
||||
bool isWorkspaceVisibleNotCovered(PHLWORKSPACE);
|
||||
PHLWORKSPACE getWorkspaceByID(const int&);
|
||||
PHLWORKSPACE getWorkspaceByID(const WORKSPACEID&);
|
||||
PHLWORKSPACE getWorkspaceByName(const std::string&);
|
||||
PHLWORKSPACE getWorkspaceByString(const std::string&);
|
||||
void sanityCheckWorkspaces();
|
||||
void updateWorkspaceWindowDecos(const int&);
|
||||
void updateWorkspaceWindowData(const int&);
|
||||
int getWindowsOnWorkspace(const int& id, std::optional<bool> onlyTiled = {}, std::optional<bool> onlyVisible = {});
|
||||
int getGroupsOnWorkspace(const int& id, std::optional<bool> onlyTiled = {}, std::optional<bool> onlyVisible = {});
|
||||
void updateWorkspaceWindowDecos(const WORKSPACEID&);
|
||||
void updateWorkspaceWindowData(const WORKSPACEID&);
|
||||
int getWindowsOnWorkspace(const WORKSPACEID& id, std::optional<bool> onlyTiled = {}, std::optional<bool> onlyVisible = {});
|
||||
int getGroupsOnWorkspace(const WORKSPACEID& id, std::optional<bool> onlyTiled = {}, std::optional<bool> onlyVisible = {});
|
||||
PHLWINDOW getUrgentWindow();
|
||||
bool hasUrgentWindowOnWorkspace(const int&);
|
||||
PHLWINDOW getFirstWindowOnWorkspace(const int&);
|
||||
PHLWINDOW getTopLeftWindowOnWorkspace(const int&);
|
||||
PHLWINDOW getFullscreenWindowOnWorkspace(const int&);
|
||||
bool hasUrgentWindowOnWorkspace(const WORKSPACEID&);
|
||||
PHLWINDOW getFirstWindowOnWorkspace(const WORKSPACEID&);
|
||||
PHLWINDOW getTopLeftWindowOnWorkspace(const WORKSPACEID&);
|
||||
PHLWINDOW getFullscreenWindowOnWorkspace(const WORKSPACEID&);
|
||||
bool isWindowActive(PHLWINDOW);
|
||||
void changeWindowZOrder(PHLWINDOW, bool);
|
||||
void cleanupFadingOut(const int& monid);
|
||||
void cleanupFadingOut(const MONITORID& monid);
|
||||
PHLWINDOW getWindowInDirection(PHLWINDOW, char);
|
||||
PHLWINDOW getNextWindowOnWorkspace(PHLWINDOW, bool focusableOnly = false, std::optional<bool> floating = {});
|
||||
PHLWINDOW getPrevWindowOnWorkspace(PHLWINDOW, bool focusableOnly = false, std::optional<bool> floating = {});
|
||||
int getNextAvailableNamedWorkspace();
|
||||
WORKSPACEID getNextAvailableNamedWorkspace();
|
||||
bool isPointOnAnyMonitor(const Vector2D&);
|
||||
bool isPointOnReservedArea(const Vector2D& point, const CMonitor* monitor = nullptr);
|
||||
CMonitor* getMonitorInDirection(const char&);
|
||||
CMonitor* getMonitorInDirection(CMonitor*, const char&);
|
||||
void updateAllWindowsAnimatedDecorationValues();
|
||||
void updateWorkspaceWindows(const int64_t& id);
|
||||
void updateWorkspaceWindows(const WORKSPACEID& id);
|
||||
void updateWindowAnimatedDecorationValues(PHLWINDOW);
|
||||
int getNextAvailableMonitorID(std::string const& name);
|
||||
MONITORID getNextAvailableMonitorID(std::string const& name);
|
||||
void moveWorkspaceToMonitor(PHLWORKSPACE, CMonitor*, bool noWarpCursor = false);
|
||||
void swapActiveWorkspaces(CMonitor*, CMonitor*);
|
||||
CMonitor* getMonitorFromString(const std::string&);
|
||||
bool workspaceIDOutOfBounds(const int64_t&);
|
||||
bool workspaceIDOutOfBounds(const WORKSPACEID&);
|
||||
void setWindowFullscreenInternal(const PHLWINDOW PWINDOW, const eFullscreenMode MODE);
|
||||
void setWindowFullscreenClient(const PHLWINDOW PWINDOW, const eFullscreenMode MODE);
|
||||
void setWindowFullscreenState(const PHLWINDOW PWINDOW, const sFullscreenState state);
|
||||
|
@ -162,12 +165,13 @@ class CCompositor {
|
|||
PHLLS getLayerSurfaceFromSurface(SP<CWLSurfaceResource>);
|
||||
void closeWindow(PHLWINDOW);
|
||||
Vector2D parseWindowVectorArgsRelative(const std::string&, const Vector2D&);
|
||||
void forceReportSizesToWindowsOnWorkspace(const int&);
|
||||
PHLWORKSPACE createNewWorkspace(const int&, const int&, const std::string& name = "", bool isEmtpy = true); // will be deleted next frame if left empty and unfocused!
|
||||
void renameWorkspace(const int&, const std::string& name = "");
|
||||
void forceReportSizesToWindowsOnWorkspace(const WORKSPACEID&);
|
||||
PHLWORKSPACE createNewWorkspace(const WORKSPACEID&, const MONITORID&, const std::string& name = "",
|
||||
bool isEmpty = true); // will be deleted next frame if left empty and unfocused!
|
||||
void renameWorkspace(const WORKSPACEID&, const std::string& name = "");
|
||||
void setActiveMonitor(CMonitor*);
|
||||
bool isWorkspaceSpecial(const int&);
|
||||
int getNewSpecialID();
|
||||
bool isWorkspaceSpecial(const WORKSPACEID&);
|
||||
WORKSPACEID getNewSpecialID();
|
||||
void performUserChecks();
|
||||
void moveWindowToWorkspaceSafe(PHLWINDOW pWindow, PHLWORKSPACE pWorkspace);
|
||||
PHLWINDOW getForceFocus();
|
||||
|
|
|
@ -52,4 +52,8 @@ struct SHyprCtlCommand {
|
|||
std::function<std::string(eHyprCtlOutputFormat, std::string)> fn;
|
||||
};
|
||||
|
||||
typedef int64_t WINDOWID;
|
||||
typedef int64_t MONITORID;
|
||||
typedef int64_t WORKSPACEID;
|
||||
|
||||
typedef std::function<void(void*, SCallbackInfo&, std::any)> HOOK_CALLBACK_FN;
|
||||
|
|
1541
src/config/ConfigDescriptions.hpp
Normal file
|
@ -3,8 +3,11 @@
|
|||
|
||||
#include "../render/decorations/CHyprGroupBarDecoration.hpp"
|
||||
#include "config/ConfigDataValues.hpp"
|
||||
#include "config/ConfigValue.hpp"
|
||||
#include "helpers/varlist/VarList.hpp"
|
||||
#include "../protocols/LayerShell.hpp"
|
||||
#include "../xwayland/XWayland.hpp"
|
||||
#include "../protocols/OutputManagement.hpp"
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
@ -29,6 +32,8 @@ using namespace Hyprutils::String;
|
|||
|
||||
extern "C" char** environ;
|
||||
|
||||
#include "ConfigDescriptions.hpp"
|
||||
|
||||
static Hyprlang::CParseResult configHandleGradientSet(const char* VALUE, void** data) {
|
||||
std::string V = VALUE;
|
||||
|
||||
|
@ -42,7 +47,7 @@ static Hyprlang::CParseResult configHandleGradientSet(const char* VALUE, void**
|
|||
|
||||
std::string parseError = "";
|
||||
|
||||
for (auto& var : varlist) {
|
||||
for (auto const& var : varlist) {
|
||||
if (var.find("deg") != std::string::npos) {
|
||||
// last arg
|
||||
try {
|
||||
|
@ -137,6 +142,18 @@ static Hyprlang::CParseResult handleExecOnce(const char* c, const char* v) {
|
|||
return result;
|
||||
}
|
||||
|
||||
static Hyprlang::CParseResult handleExecShutdown(const char* c, const char* v) {
|
||||
const std::string VALUE = v;
|
||||
const std::string COMMAND = c;
|
||||
|
||||
const auto RESULT = g_pConfigManager->handleExecShutdown(COMMAND, VALUE);
|
||||
|
||||
Hyprlang::CParseResult result;
|
||||
if (RESULT.has_value())
|
||||
result.setError(RESULT.value().c_str());
|
||||
return result;
|
||||
}
|
||||
|
||||
static Hyprlang::CParseResult handleMonitor(const char* c, const char* v) {
|
||||
const std::string VALUE = v;
|
||||
const std::string COMMAND = c;
|
||||
|
@ -311,8 +328,6 @@ CConfigManager::CConfigManager() {
|
|||
configPaths.emplace_back(getMainConfigPath());
|
||||
m_pConfig = std::make_unique<Hyprlang::CConfig>(configPaths.begin()->c_str(), Hyprlang::SConfigOptions{.throwAllErrors = true, .allowMissingConfig = true});
|
||||
|
||||
m_pConfig->addConfigValue("general:sensitivity", {1.0f});
|
||||
m_pConfig->addConfigValue("general:apply_sens_to_raw", Hyprlang::INT{0});
|
||||
m_pConfig->addConfigValue("general:border_size", Hyprlang::INT{1});
|
||||
m_pConfig->addConfigValue("general:no_border_on_floating", Hyprlang::INT{0});
|
||||
m_pConfig->addConfigValue("general:border_part_of_window", Hyprlang::INT{1});
|
||||
|
@ -346,7 +361,6 @@ CConfigManager::CConfigManager() {
|
|||
m_pConfig->addConfigValue("misc:swallow_regex", {STRVAL_EMPTY});
|
||||
m_pConfig->addConfigValue("misc:swallow_exception_regex", {STRVAL_EMPTY});
|
||||
m_pConfig->addConfigValue("misc:focus_on_activate", Hyprlang::INT{0});
|
||||
m_pConfig->addConfigValue("misc:no_direct_scanout", Hyprlang::INT{1});
|
||||
m_pConfig->addConfigValue("misc:mouse_move_focuses_monitor", Hyprlang::INT{1});
|
||||
m_pConfig->addConfigValue("misc:render_ahead_of_time", Hyprlang::INT{0});
|
||||
m_pConfig->addConfigValue("misc:render_ahead_safezone", Hyprlang::INT{1});
|
||||
|
@ -357,9 +371,15 @@ CConfigManager::CConfigManager() {
|
|||
m_pConfig->addConfigValue("misc:exit_window_retains_fullscreen", Hyprlang::INT{0});
|
||||
m_pConfig->addConfigValue("misc:initial_workspace_tracking", Hyprlang::INT{1});
|
||||
m_pConfig->addConfigValue("misc:middle_click_paste", Hyprlang::INT{1});
|
||||
m_pConfig->addConfigValue("misc:render_unfocused_fps", Hyprlang::INT{15});
|
||||
m_pConfig->addConfigValue("misc:disable_xdg_env_checks", Hyprlang::INT{0});
|
||||
|
||||
m_pConfig->addConfigValue("group:insert_after_current", Hyprlang::INT{1});
|
||||
m_pConfig->addConfigValue("group:focus_removed_window", Hyprlang::INT{1});
|
||||
m_pConfig->addConfigValue("group:merge_groups_on_drag", Hyprlang::INT{1});
|
||||
m_pConfig->addConfigValue("group:merge_floated_into_tiled_on_groupbar", Hyprlang::INT{0});
|
||||
m_pConfig->addConfigValue("group:auto_group", Hyprlang::INT{1});
|
||||
m_pConfig->addConfigValue("group:drag_into_group", Hyprlang::INT{1});
|
||||
m_pConfig->addConfigValue("group:groupbar:enabled", Hyprlang::INT{1});
|
||||
m_pConfig->addConfigValue("group:groupbar:font_family", {STRVAL_EMPTY});
|
||||
m_pConfig->addConfigValue("group:groupbar:font_size", Hyprlang::INT{8});
|
||||
|
@ -426,9 +446,9 @@ CConfigManager::CConfigManager() {
|
|||
m_pConfig->addConfigValue("dwindle:preserve_split", Hyprlang::INT{0});
|
||||
m_pConfig->addConfigValue("dwindle:special_scale_factor", {1.f});
|
||||
m_pConfig->addConfigValue("dwindle:split_width_multiplier", {1.0f});
|
||||
m_pConfig->addConfigValue("dwindle:no_gaps_when_only", Hyprlang::INT{0});
|
||||
m_pConfig->addConfigValue("dwindle:use_active_for_splits", Hyprlang::INT{1});
|
||||
m_pConfig->addConfigValue("dwindle:default_split_ratio", {1.f});
|
||||
m_pConfig->addConfigValue("dwindle:split_bias", Hyprlang::INT{0});
|
||||
m_pConfig->addConfigValue("dwindle:smart_split", Hyprlang::INT{0});
|
||||
m_pConfig->addConfigValue("dwindle:smart_resizing", Hyprlang::INT{1});
|
||||
|
||||
|
@ -438,7 +458,6 @@ CConfigManager::CConfigManager() {
|
|||
m_pConfig->addConfigValue("master:always_center_master", Hyprlang::INT{0});
|
||||
m_pConfig->addConfigValue("master:new_on_active", {"none"});
|
||||
m_pConfig->addConfigValue("master:new_on_top", Hyprlang::INT{0});
|
||||
m_pConfig->addConfigValue("master:no_gaps_when_only", Hyprlang::INT{0});
|
||||
m_pConfig->addConfigValue("master:orientation", {"left"});
|
||||
m_pConfig->addConfigValue("master:inherit_fullscreen", Hyprlang::INT{1});
|
||||
m_pConfig->addConfigValue("master:allow_small_split", Hyprlang::INT{0});
|
||||
|
@ -449,6 +468,7 @@ CConfigManager::CConfigManager() {
|
|||
m_pConfig->addConfigValue("animations:first_launch_animation", Hyprlang::INT{1});
|
||||
|
||||
m_pConfig->addConfigValue("input:follow_mouse", Hyprlang::INT{1});
|
||||
m_pConfig->addConfigValue("input:focus_on_close", Hyprlang::INT{0});
|
||||
m_pConfig->addConfigValue("input:mouse_refocus", Hyprlang::INT{1});
|
||||
m_pConfig->addConfigValue("input:special_fallthrough", Hyprlang::INT{0});
|
||||
m_pConfig->addConfigValue("input:off_window_axis_events", Hyprlang::INT{1});
|
||||
|
@ -521,6 +541,7 @@ CConfigManager::CConfigManager() {
|
|||
m_pConfig->addConfigValue("gestures:workspace_swipe_touch", Hyprlang::INT{0});
|
||||
m_pConfig->addConfigValue("gestures:workspace_swipe_touch_invert", Hyprlang::INT{0});
|
||||
|
||||
m_pConfig->addConfigValue("xwayland:enabled", Hyprlang::INT{1});
|
||||
m_pConfig->addConfigValue("xwayland:use_nearest_neighbor", Hyprlang::INT{1});
|
||||
m_pConfig->addConfigValue("xwayland:force_zero_scaling", Hyprlang::INT{0});
|
||||
|
||||
|
@ -531,7 +552,7 @@ CConfigManager::CConfigManager() {
|
|||
m_pConfig->addConfigValue("cursor:no_break_fs_vrr", Hyprlang::INT{0});
|
||||
m_pConfig->addConfigValue("cursor:min_refresh_rate", Hyprlang::INT{24});
|
||||
m_pConfig->addConfigValue("cursor:hotspot_padding", Hyprlang::INT{0});
|
||||
m_pConfig->addConfigValue("cursor:inactive_timeout", Hyprlang::INT{0});
|
||||
m_pConfig->addConfigValue("cursor:inactive_timeout", {0.f});
|
||||
m_pConfig->addConfigValue("cursor:no_warps", Hyprlang::INT{0});
|
||||
m_pConfig->addConfigValue("cursor:persistent_warps", Hyprlang::INT{0});
|
||||
m_pConfig->addConfigValue("cursor:warp_on_change_workspace", Hyprlang::INT{0});
|
||||
|
@ -539,6 +560,7 @@ CConfigManager::CConfigManager() {
|
|||
m_pConfig->addConfigValue("cursor:zoom_factor", {1.f});
|
||||
m_pConfig->addConfigValue("cursor:zoom_rigid", Hyprlang::INT{0});
|
||||
m_pConfig->addConfigValue("cursor:enable_hyprcursor", Hyprlang::INT{1});
|
||||
m_pConfig->addConfigValue("cursor:sync_gsettings_theme", Hyprlang::INT{1});
|
||||
m_pConfig->addConfigValue("cursor:hide_on_key_press", Hyprlang::INT{0});
|
||||
m_pConfig->addConfigValue("cursor:hide_on_touch", Hyprlang::INT{1});
|
||||
m_pConfig->addConfigValue("cursor:allow_dumb_copy", Hyprlang::INT{0});
|
||||
|
@ -560,7 +582,9 @@ CConfigManager::CConfigManager() {
|
|||
m_pConfig->addConfigValue("group:groupbar:col.locked_active", Hyprlang::CConfigCustomValueType{&configHandleGradientSet, configHandleGradientDestroy, "0x66ff5500"});
|
||||
m_pConfig->addConfigValue("group:groupbar:col.locked_inactive", Hyprlang::CConfigCustomValueType{&configHandleGradientSet, configHandleGradientDestroy, "0x66775500"});
|
||||
|
||||
m_pConfig->addConfigValue("experimental:explicit_sync", Hyprlang::INT{0});
|
||||
m_pConfig->addConfigValue("render:explicit_sync", Hyprlang::INT{2});
|
||||
m_pConfig->addConfigValue("render:explicit_sync_kms", Hyprlang::INT{2});
|
||||
m_pConfig->addConfigValue("render:direct_scanout", Hyprlang::INT{0});
|
||||
|
||||
// devices
|
||||
m_pConfig->addSpecialCategory("device", {"name"});
|
||||
|
@ -601,6 +625,7 @@ CConfigManager::CConfigManager() {
|
|||
// keywords
|
||||
m_pConfig->registerHandler(&::handleRawExec, "exec", {false});
|
||||
m_pConfig->registerHandler(&::handleExecOnce, "exec-once", {false});
|
||||
m_pConfig->registerHandler(&::handleExecShutdown, "exec-shutdown", {false});
|
||||
m_pConfig->registerHandler(&::handleMonitor, "monitor", {false});
|
||||
m_pConfig->registerHandler(&::handleBind, "bind", {true});
|
||||
m_pConfig->registerHandler(&::handleUnbind, "unbind", {false});
|
||||
|
@ -661,6 +686,10 @@ std::string CConfigManager::getMainConfigPath() {
|
|||
if (!g_pCompositor->explicitConfigPath.empty())
|
||||
return g_pCompositor->explicitConfigPath;
|
||||
|
||||
if (const auto CFG_ENV = getenv("HYPRLAND_CONFIG"); CFG_ENV)
|
||||
return CFG_ENV;
|
||||
Debug::log(TRACE, "Seems as if HYPRLAND_CONFIG isn't set, let's see what we can do with HOME.");
|
||||
|
||||
static const auto paths = Hyprutils::Path::findConfig(ISDEBUG ? "hyprlandd" : "hyprland");
|
||||
if (paths.first.has_value()) {
|
||||
return paths.first.value();
|
||||
|
@ -720,7 +749,6 @@ void CConfigManager::setDefaultAnimationVars() {
|
|||
INITANIMCFG("fade");
|
||||
INITANIMCFG("border");
|
||||
INITANIMCFG("borderangle");
|
||||
INITANIMCFG("workspaces");
|
||||
|
||||
// windows
|
||||
INITANIMCFG("windowsIn");
|
||||
|
@ -741,7 +769,12 @@ void CConfigManager::setDefaultAnimationVars() {
|
|||
// border
|
||||
|
||||
// workspaces
|
||||
INITANIMCFG("workspaces");
|
||||
INITANIMCFG("workspacesIn");
|
||||
INITANIMCFG("workspacesOut");
|
||||
INITANIMCFG("specialWorkspace");
|
||||
INITANIMCFG("specialWorkspaceIn");
|
||||
INITANIMCFG("specialWorkspaceOut");
|
||||
}
|
||||
|
||||
// init the values
|
||||
|
@ -770,7 +803,11 @@ void CConfigManager::setDefaultAnimationVars() {
|
|||
CREATEANIMCFG("fadeLayersIn", "fadeLayers");
|
||||
CREATEANIMCFG("fadeLayersOut", "fadeLayers");
|
||||
|
||||
CREATEANIMCFG("workspacesIn", "workspaces");
|
||||
CREATEANIMCFG("workspacesOut", "workspaces");
|
||||
CREATEANIMCFG("specialWorkspace", "workspaces");
|
||||
CREATEANIMCFG("specialWorkspaceIn", "specialWorkspace");
|
||||
CREATEANIMCFG("specialWorkspaceOut", "specialWorkspace");
|
||||
}
|
||||
|
||||
std::optional<std::string> CConfigManager::resetHLConfig() {
|
||||
|
@ -785,6 +822,7 @@ std::optional<std::string> CConfigManager::resetHLConfig() {
|
|||
m_vDeclaredPlugins.clear();
|
||||
m_dLayerRules.clear();
|
||||
m_vFailedPluginConfigValues.clear();
|
||||
finalExecRequests.clear();
|
||||
|
||||
// paths
|
||||
configPaths.clear();
|
||||
|
@ -798,11 +836,14 @@ std::optional<std::string> CConfigManager::resetHLConfig() {
|
|||
}
|
||||
|
||||
void CConfigManager::postConfigReload(const Hyprlang::CParseResult& result) {
|
||||
for (auto& w : g_pCompositor->m_vWindows) {
|
||||
static const auto PENABLEEXPLICIT = CConfigValue<Hyprlang::INT>("render:explicit_sync");
|
||||
static int prevEnabledExplicit = *PENABLEEXPLICIT;
|
||||
|
||||
for (auto const& w : g_pCompositor->m_vWindows) {
|
||||
w->uncacheWindowDecos();
|
||||
}
|
||||
|
||||
for (auto& m : g_pCompositor->m_vMonitors)
|
||||
for (auto const& m : g_pCompositor->m_vMonitors)
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m->ID);
|
||||
|
||||
// Update the keyboard layout to the cfg'd one if this is not the first launch
|
||||
|
@ -826,8 +867,12 @@ void CConfigManager::postConfigReload(const Hyprlang::CParseResult& result) {
|
|||
if (result.error && !std::any_cast<Hyprlang::INT>(m_pConfig->getConfigValue("debug:suppress_errors")))
|
||||
g_pHyprError->queueCreate(result.getError(), CColor(1.0, 50.0 / 255.0, 50.0 / 255.0, 1.0));
|
||||
else if (std::any_cast<Hyprlang::INT>(m_pConfig->getConfigValue("autogenerated")) == 1)
|
||||
g_pHyprError->queueCreate("Warning: You're using an autogenerated config! (config file: " + getMainConfigPath() + " )\nSUPER+Q -> kitty\nSUPER+M -> exit Hyprland",
|
||||
g_pHyprError->queueCreate(
|
||||
"Warning: You're using an autogenerated config! (config file: " + getMainConfigPath() +
|
||||
" )\nSUPER+Q -> kitty (if it doesn't launch, make sure it's installed or choose a different terminal in the config)\nSUPER+M -> exit Hyprland",
|
||||
CColor(1.0, 1.0, 70.0 / 255.0, 1.0));
|
||||
else if (*PENABLEEXPLICIT != prevEnabledExplicit)
|
||||
g_pHyprError->queueCreate("Warning: You changed the render:explicit_sync option, this requires you to restart Hyprland.", CColor(0.9, 0.76, 0.221, 1.0));
|
||||
else
|
||||
g_pHyprError->destroy();
|
||||
|
||||
|
@ -842,11 +887,34 @@ void CConfigManager::postConfigReload(const Hyprlang::CParseResult& result) {
|
|||
ensureVRR();
|
||||
}
|
||||
|
||||
#ifndef NO_XWAYLAND
|
||||
const auto PENABLEXWAYLAND = std::any_cast<Hyprlang::INT>(m_pConfig->getConfigValue("xwayland:enabled"));
|
||||
// enable/disable xwayland usage
|
||||
if (!isFirstLaunch) {
|
||||
bool prevEnabledXwayland = g_pCompositor->m_bEnableXwayland;
|
||||
if (PENABLEXWAYLAND != prevEnabledXwayland) {
|
||||
g_pCompositor->m_bEnableXwayland = PENABLEXWAYLAND;
|
||||
if (PENABLEXWAYLAND) {
|
||||
Debug::log(LOG, "xwayland has been enabled");
|
||||
} else {
|
||||
Debug::log(LOG, "xwayland has been disabled, cleaning up...");
|
||||
for (auto& w : g_pCompositor->m_vWindows) {
|
||||
if (w->m_pXDGSurface || !w->m_bIsX11)
|
||||
continue;
|
||||
g_pCompositor->closeWindow(w);
|
||||
}
|
||||
}
|
||||
g_pXWayland = std::make_unique<CXWayland>(g_pCompositor->m_bEnableXwayland);
|
||||
}
|
||||
} else
|
||||
g_pCompositor->m_bEnableXwayland = PENABLEXWAYLAND;
|
||||
#endif
|
||||
|
||||
if (!isFirstLaunch && !g_pCompositor->m_bUnsafeState)
|
||||
refreshGroupBarGradients();
|
||||
|
||||
// Updates dynamic window and workspace rules
|
||||
for (auto& w : g_pCompositor->m_vWorkspaces) {
|
||||
for (auto const& w : g_pCompositor->m_vWorkspaces) {
|
||||
if (w->inert())
|
||||
continue;
|
||||
g_pCompositor->updateWorkspaceWindows(w->m_iID);
|
||||
|
@ -874,7 +942,7 @@ void CConfigManager::postConfigReload(const Hyprlang::CParseResult& result) {
|
|||
|
||||
Debug::coloredLogs = reinterpret_cast<int64_t* const*>(m_pConfig->getConfigValuePtr("debug:colored_stdout_logs")->getDataStaticPtr());
|
||||
|
||||
for (auto& m : g_pCompositor->m_vMonitors) {
|
||||
for (auto const& m : g_pCompositor->m_vMonitors) {
|
||||
// mark blur dirty
|
||||
g_pHyprOpenGL->markBlurDirtyForMonitor(m.get());
|
||||
|
||||
|
@ -884,7 +952,7 @@ void CConfigManager::postConfigReload(const Hyprlang::CParseResult& result) {
|
|||
m->forceFullFrames = 2;
|
||||
|
||||
// also force mirrors, as the aspect ratio could've changed
|
||||
for (auto& mirror : m->mirrors)
|
||||
for (auto const& mirror : m->mirrors)
|
||||
mirror->forceFullFrames = 3;
|
||||
}
|
||||
|
||||
|
@ -916,14 +984,24 @@ void CConfigManager::init() {
|
|||
}
|
||||
|
||||
std::string CConfigManager::parseKeyword(const std::string& COMMAND, const std::string& VALUE) {
|
||||
static const auto PENABLEEXPLICIT = CConfigValue<Hyprlang::INT>("render:explicit_sync");
|
||||
static int prevEnabledExplicit = *PENABLEEXPLICIT;
|
||||
|
||||
const auto RET = m_pConfig->parseDynamic(COMMAND.c_str(), VALUE.c_str());
|
||||
|
||||
// invalidate layouts if they changed
|
||||
if (COMMAND == "monitor" || COMMAND.contains("gaps_") || COMMAND.starts_with("dwindle:") || COMMAND.starts_with("master:")) {
|
||||
for (auto& m : g_pCompositor->m_vMonitors)
|
||||
for (auto const& m : g_pCompositor->m_vMonitors)
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m->ID);
|
||||
}
|
||||
|
||||
if (COMMAND.contains("explicit")) {
|
||||
if (*PENABLEEXPLICIT != prevEnabledExplicit)
|
||||
g_pHyprError->queueCreate("Warning: You changed the render:explicit_sync option, this requires you to restart Hyprland.", CColor(0.9, 0.76, 0.221, 1.0));
|
||||
else
|
||||
g_pHyprError->destroy();
|
||||
}
|
||||
|
||||
// Update window border colors
|
||||
g_pCompositor->updateAllWindowsAnimatedDecorationValues();
|
||||
|
||||
|
@ -951,7 +1029,7 @@ void CConfigManager::tick() {
|
|||
|
||||
bool parse = false;
|
||||
|
||||
for (auto& cf : configPaths) {
|
||||
for (auto const& cf : configPaths) {
|
||||
struct stat fileStat;
|
||||
int err = stat(cf.c_str(), &fileStat);
|
||||
if (err != 0) {
|
||||
|
@ -1006,33 +1084,74 @@ std::string CConfigManager::getDeviceString(const std::string& dev, const std::s
|
|||
return VAL;
|
||||
}
|
||||
|
||||
SMonitorRule CConfigManager::getMonitorRuleFor(const CMonitor& PMONITOR) {
|
||||
for (auto& r : m_dMonitorRules | std::views::reverse) {
|
||||
if (PMONITOR.matchesStaticSelector(r.name)) {
|
||||
return r;
|
||||
SMonitorRule CConfigManager::getMonitorRuleFor(const SP<CMonitor> PMONITOR) {
|
||||
auto applyWlrOutputConfig = [PMONITOR](SMonitorRule rule) -> SMonitorRule {
|
||||
const auto CONFIG = PROTO::outputManagement->getOutputStateFor(PMONITOR);
|
||||
|
||||
if (!CONFIG)
|
||||
return rule;
|
||||
|
||||
Debug::log(LOG, "CConfigManager::getMonitorRuleFor: found a wlr_output_manager override for {}", PMONITOR->szName);
|
||||
|
||||
Debug::log(LOG, " > overriding enabled: {} -> {}", !rule.disabled, !CONFIG->enabled);
|
||||
rule.disabled = !CONFIG->enabled;
|
||||
|
||||
if ((CONFIG->committedProperties & OUTPUT_HEAD_COMMITTED_MODE) || (CONFIG->committedProperties & OUTPUT_HEAD_COMMITTED_CUSTOM_MODE)) {
|
||||
Debug::log(LOG, " > overriding mode: {:.0f}x{:.0f}@{:.2f}Hz -> {:.0f}x{:.0f}@{:.2f}Hz", rule.resolution.x, rule.resolution.y, rule.refreshRate, CONFIG->resolution.x,
|
||||
CONFIG->resolution.y, CONFIG->refresh / 1000.F);
|
||||
rule.resolution = CONFIG->resolution;
|
||||
rule.refreshRate = CONFIG->refresh / 1000.F;
|
||||
}
|
||||
|
||||
if (CONFIG->committedProperties & OUTPUT_HEAD_COMMITTED_POSITION) {
|
||||
Debug::log(LOG, " > overriding offset: {:.0f}, {:.0f} -> {:.0f}, {:.0f}", rule.offset.x, rule.offset.y, CONFIG->position.x, CONFIG->position.y);
|
||||
rule.offset = CONFIG->position;
|
||||
}
|
||||
|
||||
if (CONFIG->committedProperties & OUTPUT_HEAD_COMMITTED_TRANSFORM) {
|
||||
Debug::log(LOG, " > overriding transform: {} -> {}", (uint8_t)rule.transform, (uint8_t)CONFIG->transform);
|
||||
rule.transform = CONFIG->transform;
|
||||
}
|
||||
|
||||
if (CONFIG->committedProperties & OUTPUT_HEAD_COMMITTED_SCALE) {
|
||||
Debug::log(LOG, " > overriding scale: {} -> {}", (uint8_t)rule.scale, (uint8_t)CONFIG->scale);
|
||||
rule.scale = CONFIG->scale;
|
||||
}
|
||||
|
||||
if (CONFIG->committedProperties & OUTPUT_HEAD_COMMITTED_ADAPTIVE_SYNC) {
|
||||
Debug::log(LOG, " > overriding vrr: {} -> {}", rule.vrr.value_or(0), CONFIG->adaptiveSync);
|
||||
rule.vrr = (int)CONFIG->adaptiveSync;
|
||||
}
|
||||
|
||||
return rule;
|
||||
};
|
||||
|
||||
for (auto const& r : m_dMonitorRules | std::views::reverse) {
|
||||
if (PMONITOR->matchesStaticSelector(r.name)) {
|
||||
return applyWlrOutputConfig(r);
|
||||
}
|
||||
}
|
||||
|
||||
Debug::log(WARN, "No rule found for {}, trying to use the first.", PMONITOR.szName);
|
||||
Debug::log(WARN, "No rule found for {}, trying to use the first.", PMONITOR->szName);
|
||||
|
||||
for (auto& r : m_dMonitorRules) {
|
||||
for (auto const& r : m_dMonitorRules) {
|
||||
if (r.name.empty()) {
|
||||
return r;
|
||||
return applyWlrOutputConfig(r);
|
||||
}
|
||||
}
|
||||
|
||||
Debug::log(WARN, "No rules configured. Using the default hardcoded one.");
|
||||
|
||||
return SMonitorRule{.autoDir = eAutoDirs::DIR_AUTO_RIGHT,
|
||||
return applyWlrOutputConfig(SMonitorRule{.autoDir = eAutoDirs::DIR_AUTO_RIGHT,
|
||||
.name = "",
|
||||
.resolution = Vector2D(0, 0),
|
||||
.offset = Vector2D(-INT32_MAX, -INT32_MAX),
|
||||
.scale = -1}; // 0, 0 is preferred and -1, -1 is auto
|
||||
.scale = -1}); // 0, 0 is preferred and -1, -1 is auto
|
||||
}
|
||||
|
||||
SWorkspaceRule CConfigManager::getWorkspaceRuleFor(PHLWORKSPACE pWorkspace) {
|
||||
SWorkspaceRule mergedRule{};
|
||||
for (auto& rule : m_dWorkspaceRules) {
|
||||
for (auto const& rule : m_dWorkspaceRules) {
|
||||
if (!pWorkspace->matchesStaticSelector(rule.workspaceString))
|
||||
continue;
|
||||
|
||||
|
@ -1105,7 +1224,7 @@ std::vector<SWindowRule> CConfigManager::getMatchingRules(PHLWINDOW pWindow, boo
|
|||
// local tags for dynamic tag rule match
|
||||
auto tags = pWindow->m_tags;
|
||||
|
||||
for (auto& rule : m_dWindowRules) {
|
||||
for (auto const& rule : m_dWindowRules) {
|
||||
// check if we have a matching rule
|
||||
if (!rule.v2) {
|
||||
try {
|
||||
|
@ -1185,6 +1304,32 @@ std::vector<SWindowRule> CConfigManager::getMatchingRules(PHLWINDOW pWindow, boo
|
|||
continue;
|
||||
}
|
||||
|
||||
if (!rule.szFullscreenState.empty()) {
|
||||
const auto ARGS = CVarList(rule.szFullscreenState, 2, ' ');
|
||||
//
|
||||
std::optional<eFullscreenMode> internalMode, clientMode;
|
||||
|
||||
if (ARGS[0] == "*")
|
||||
internalMode = std::nullopt;
|
||||
else if (isNumber(ARGS[0]))
|
||||
internalMode = (eFullscreenMode)std::stoi(ARGS[0]);
|
||||
else
|
||||
throw std::runtime_error("szFullscreenState internal mode not valid");
|
||||
|
||||
if (ARGS[1] == "*")
|
||||
clientMode = std::nullopt;
|
||||
else if (isNumber(ARGS[1]))
|
||||
clientMode = (eFullscreenMode)std::stoi(ARGS[1]);
|
||||
else
|
||||
throw std::runtime_error("szFullscreenState client mode not valid");
|
||||
|
||||
if (internalMode.has_value() && pWindow->m_sFullscreenState.internal != internalMode)
|
||||
continue;
|
||||
|
||||
if (clientMode.has_value() && pWindow->m_sFullscreenState.client != clientMode)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!rule.szOnWorkspace.empty()) {
|
||||
const auto PWORKSPACE = pWindow->m_pWorkspace;
|
||||
if (!PWORKSPACE || !PWORKSPACE->matchesStaticSelector(rule.szOnWorkspace))
|
||||
|
@ -1244,7 +1389,7 @@ std::vector<SWindowRule> CConfigManager::getMatchingRules(PHLWINDOW pWindow, boo
|
|||
|
||||
bool anyExecFound = false;
|
||||
|
||||
for (auto& er : execRequestedRules) {
|
||||
for (auto const& er : execRequestedRules) {
|
||||
if (std::ranges::any_of(PIDs, [&](const auto& pid) { return pid == er.iPid; })) {
|
||||
returns.push_back({er.szRule, "execRule"});
|
||||
anyExecFound = true;
|
||||
|
@ -1264,7 +1409,7 @@ std::vector<SLayerRule> CConfigManager::getMatchingRules(PHLLS pLS) {
|
|||
if (!pLS->layerSurface || pLS->fadingOut)
|
||||
return returns;
|
||||
|
||||
for (auto& lr : m_dLayerRules) {
|
||||
for (auto const& lr : m_dLayerRules) {
|
||||
if (lr.targetNamespace.starts_with("address:0x")) {
|
||||
if (std::format("address:0x{:x}", (uintptr_t)pLS.get()) != lr.targetNamespace)
|
||||
continue;
|
||||
|
@ -1301,7 +1446,7 @@ void CConfigManager::dispatchExecOnce() {
|
|||
firstExecDispatched = true;
|
||||
isLaunchingExecOnce = true;
|
||||
|
||||
for (auto& c : firstExecRequests) {
|
||||
for (auto const& c : firstExecRequests) {
|
||||
handleRawExec("", c);
|
||||
}
|
||||
|
||||
|
@ -1318,6 +1463,24 @@ void CConfigManager::dispatchExecOnce() {
|
|||
g_pCompositor->performUserChecks();
|
||||
}
|
||||
|
||||
void CConfigManager::dispatchExecShutdown() {
|
||||
if (finalExecRequests.empty()) {
|
||||
g_pCompositor->m_bFinalRequests = false;
|
||||
return;
|
||||
}
|
||||
|
||||
g_pCompositor->m_bFinalRequests = true;
|
||||
|
||||
for (auto const& c : finalExecRequests) {
|
||||
handleExecShutdown("", c);
|
||||
}
|
||||
|
||||
finalExecRequests.clear();
|
||||
|
||||
// Actually exit now
|
||||
handleExecShutdown("", "hyprctl dispatch exit");
|
||||
}
|
||||
|
||||
void CConfigManager::appendMonitorRule(const SMonitorRule& r) {
|
||||
m_dMonitorRules.emplace_back(r);
|
||||
}
|
||||
|
@ -1338,11 +1501,11 @@ void CConfigManager::performMonitorReload() {
|
|||
|
||||
bool overAgain = false;
|
||||
|
||||
for (auto& m : g_pCompositor->m_vRealMonitors) {
|
||||
for (auto const& m : g_pCompositor->m_vRealMonitors) {
|
||||
if (!m->output || m->isUnsafeFallback)
|
||||
continue;
|
||||
|
||||
auto rule = getMonitorRuleFor(*m);
|
||||
auto rule = getMonitorRuleFor(m);
|
||||
|
||||
if (!g_pHyprRenderer->applyMonitorRule(m.get(), &rule)) {
|
||||
overAgain = true;
|
||||
|
@ -1385,7 +1548,7 @@ bool CConfigManager::deviceConfigExists(const std::string& dev) {
|
|||
}
|
||||
|
||||
bool CConfigManager::shouldBlurLS(const std::string& ns) {
|
||||
for (auto& bls : m_dBlurLSNamespaces) {
|
||||
for (auto const& bls : m_dBlurLSNamespaces) {
|
||||
if (bls == ns) {
|
||||
return true;
|
||||
}
|
||||
|
@ -1395,11 +1558,11 @@ bool CConfigManager::shouldBlurLS(const std::string& ns) {
|
|||
}
|
||||
|
||||
void CConfigManager::ensureMonitorStatus() {
|
||||
for (auto& rm : g_pCompositor->m_vRealMonitors) {
|
||||
for (auto const& rm : g_pCompositor->m_vRealMonitors) {
|
||||
if (!rm->output || rm->isUnsafeFallback)
|
||||
continue;
|
||||
|
||||
auto rule = getMonitorRuleFor(*rm);
|
||||
auto rule = getMonitorRuleFor(rm);
|
||||
|
||||
if (rule.disabled == rm->m_bEnabled)
|
||||
g_pHyprRenderer->applyMonitorRule(rm.get(), &rule);
|
||||
|
@ -1417,7 +1580,7 @@ void CConfigManager::ensureVRR(CMonitor* pMonitor) {
|
|||
|
||||
if (USEVRR == 0) {
|
||||
if (m->vrrActive) {
|
||||
|
||||
m->output->state->resetExplicitFences();
|
||||
m->output->state->setAdaptiveSync(false);
|
||||
|
||||
if (!m->state.commit())
|
||||
|
@ -1427,6 +1590,7 @@ void CConfigManager::ensureVRR(CMonitor* pMonitor) {
|
|||
return;
|
||||
} else if (USEVRR == 1) {
|
||||
if (!m->vrrActive) {
|
||||
m->output->state->resetExplicitFences();
|
||||
m->output->state->setAdaptiveSync(true);
|
||||
|
||||
if (!m->state.test()) {
|
||||
|
@ -1451,6 +1615,7 @@ void CConfigManager::ensureVRR(CMonitor* pMonitor) {
|
|||
const auto WORKSPACEFULL = PWORKSPACE->m_bHasFullscreenWindow && (PWORKSPACE->m_efFullscreenMode & FSMODE_FULLSCREEN);
|
||||
|
||||
if (WORKSPACEFULL) {
|
||||
m->output->state->resetExplicitFences();
|
||||
m->output->state->setAdaptiveSync(true);
|
||||
|
||||
if (!m->state.test()) {
|
||||
|
@ -1462,6 +1627,7 @@ void CConfigManager::ensureVRR(CMonitor* pMonitor) {
|
|||
Debug::log(ERR, "Couldn't commit output {} in ensureVRR -> true", m->output->name);
|
||||
|
||||
} else if (!WORKSPACEFULL) {
|
||||
m->output->state->resetExplicitFences();
|
||||
m->output->state->setAdaptiveSync(false);
|
||||
|
||||
if (!m->state.commit())
|
||||
|
@ -1475,7 +1641,7 @@ void CConfigManager::ensureVRR(CMonitor* pMonitor) {
|
|||
return;
|
||||
}
|
||||
|
||||
for (auto& m : g_pCompositor->m_vMonitors) {
|
||||
for (auto const& m : g_pCompositor->m_vMonitors) {
|
||||
ensureVRRForDisplay(m.get());
|
||||
}
|
||||
}
|
||||
|
@ -1497,7 +1663,7 @@ CMonitor* CConfigManager::getBoundMonitorForWS(const std::string& wsname) {
|
|||
}
|
||||
|
||||
std::string CConfigManager::getBoundMonitorStringForWS(const std::string& wsname) {
|
||||
for (auto& wr : m_dWorkspaceRules) {
|
||||
for (auto const& wr : m_dWorkspaceRules) {
|
||||
const auto WSNAME = wr.workspaceName.starts_with("name:") ? wr.workspaceName.substr(5) : wr.workspaceName;
|
||||
|
||||
if (WSNAME == wsname)
|
||||
|
@ -1568,7 +1734,7 @@ void CConfigManager::addPluginKeyword(HANDLE handle, const std::string& name, Hy
|
|||
}
|
||||
|
||||
void CConfigManager::removePluginConfig(HANDLE handle) {
|
||||
for (auto& k : pluginKeywords) {
|
||||
for (auto const& k : pluginKeywords) {
|
||||
if (k.handle != handle)
|
||||
continue;
|
||||
|
||||
|
@ -1576,7 +1742,7 @@ void CConfigManager::removePluginConfig(HANDLE handle) {
|
|||
}
|
||||
|
||||
std::erase_if(pluginKeywords, [&](const auto& other) { return other.handle == handle; });
|
||||
for (auto& [h, n] : pluginVariables) {
|
||||
for (auto const& [h, n] : pluginVariables) {
|
||||
if (h != handle)
|
||||
continue;
|
||||
|
||||
|
@ -1591,7 +1757,7 @@ std::string CConfigManager::getDefaultWorkspaceFor(const std::string& name) {
|
|||
if (other->monitor == name)
|
||||
return other->workspaceString;
|
||||
if (other->monitor.substr(0, 5) == "desc:") {
|
||||
auto monitor = g_pCompositor->getMonitorFromDesc(other->monitor.substr(5));
|
||||
auto const monitor = g_pCompositor->getMonitorFromDesc(other->monitor.substr(5));
|
||||
if (monitor && monitor->szName == name)
|
||||
return other->workspaceString;
|
||||
}
|
||||
|
@ -1617,6 +1783,16 @@ std::optional<std::string> CConfigManager::handleExecOnce(const std::string& com
|
|||
return {};
|
||||
}
|
||||
|
||||
std::optional<std::string> CConfigManager::handleExecShutdown(const std::string& command, const std::string& args) {
|
||||
if (g_pCompositor->m_bFinalRequests) {
|
||||
g_pKeybindManager->spawn(args);
|
||||
return {};
|
||||
}
|
||||
|
||||
finalExecRequests.push_back(args);
|
||||
return {};
|
||||
}
|
||||
|
||||
static bool parseModeLine(const std::string& modeline, drmModeModeInfo& mode) {
|
||||
auto args = CVarList(modeline, 0, 's');
|
||||
|
||||
|
@ -1664,7 +1840,7 @@ static bool parseModeLine(const std::string& modeline, drmModeModeInfo& mode) {
|
|||
if (it != flagsmap.end())
|
||||
mode.flags |= it->second;
|
||||
else
|
||||
Debug::log(ERR, "invalid flag {} in modeline", it->first);
|
||||
Debug::log(ERR, "invalid flag {} in modeline", key);
|
||||
}
|
||||
|
||||
snprintf(mode.name, sizeof(mode.name), "%dx%d@%d", mode.hdisplay, mode.vdisplay, mode.vrefresh / 1000);
|
||||
|
@ -1988,7 +2164,7 @@ std::optional<std::string> CConfigManager::handleBind(const std::string& command
|
|||
bool dontInhibit = false;
|
||||
const auto BINDARGS = command.substr(4);
|
||||
|
||||
for (auto& arg : BINDARGS) {
|
||||
for (auto const& arg : BINDARGS) {
|
||||
if (arg == 'l') {
|
||||
locked = true;
|
||||
} else if (arg == 'r') {
|
||||
|
@ -2099,7 +2275,7 @@ std::optional<std::string> CConfigManager::handleUnbind(const std::string& comma
|
|||
|
||||
bool windowRuleValid(const std::string& RULE) {
|
||||
static const auto rules = std::unordered_set<std::string>{
|
||||
"float", "fullscreen", "maximize", "noinitialfocus", "pin", "stayfocused", "tile",
|
||||
"float", "fullscreen", "maximize", "noinitialfocus", "pin", "stayfocused", "tile", "renderunfocused",
|
||||
};
|
||||
static const auto rulesPrefix = std::vector<std::string>{
|
||||
"animation", "bordercolor", "bordersize", "center", "fullscreenstate", "group", "idleinhibit", "maxsize", "minsize", "monitor",
|
||||
|
@ -2114,7 +2290,7 @@ bool windowRuleValid(const std::string& RULE) {
|
|||
|
||||
bool layerRuleValid(const std::string& RULE) {
|
||||
static const auto rules = std::unordered_set<std::string>{"noanim", "blur", "blurpopups", "dimaround"};
|
||||
static const auto rulesPrefix = std::vector<std::string>{"ignorealpha", "ignorezero", "xray", "animation"};
|
||||
static const auto rulesPrefix = std::vector<std::string>{"ignorealpha", "ignorezero", "xray", "animation", "order"};
|
||||
|
||||
return rules.contains(RULE) || std::any_of(rulesPrefix.begin(), rulesPrefix.end(), [&RULE](auto prefix) { return RULE.starts_with(prefix); });
|
||||
}
|
||||
|
@ -2166,9 +2342,9 @@ std::optional<std::string> CConfigManager::handleLayerRule(const std::string& co
|
|||
|
||||
m_dLayerRules.push_back({VALUE, RULE});
|
||||
|
||||
for (auto& m : g_pCompositor->m_vMonitors)
|
||||
for (auto& lsl : m->m_aLayerSurfaceLayers)
|
||||
for (auto& ls : lsl)
|
||||
for (auto const& m : g_pCompositor->m_vMonitors)
|
||||
for (auto const& lsl : m->m_aLayerSurfaceLayers)
|
||||
for (auto const& ls : lsl)
|
||||
ls->applyRules();
|
||||
|
||||
return {};
|
||||
|
@ -2199,6 +2375,7 @@ std::optional<std::string> CConfigManager::handleWindowRuleV2(const std::string&
|
|||
const auto FULLSCREENPOS = VALUE.find("fullscreen:");
|
||||
const auto PINNEDPOS = VALUE.find("pinned:");
|
||||
const auto FOCUSPOS = VALUE.find("focus:");
|
||||
const auto FULLSCREENSTATEPOS = VALUE.find("fullscreenstate:");
|
||||
const auto ONWORKSPACEPOS = VALUE.find("onworkspace:");
|
||||
|
||||
// find workspacepos that isn't onworkspacepos
|
||||
|
@ -2212,9 +2389,8 @@ std::optional<std::string> CConfigManager::handleWindowRuleV2(const std::string&
|
|||
currentPos = VALUE.find("workspace:", currentPos + 1);
|
||||
}
|
||||
|
||||
const auto checkPos = std::unordered_set{
|
||||
TAGPOS, TITLEPOS, CLASSPOS, INITIALTITLEPOS, INITIALCLASSPOS, X11POS, FLOATPOS, FULLSCREENPOS, PINNEDPOS, WORKSPACEPOS, FOCUSPOS, ONWORKSPACEPOS,
|
||||
};
|
||||
const auto checkPos = std::unordered_set{TAGPOS, TITLEPOS, CLASSPOS, INITIALTITLEPOS, INITIALCLASSPOS, X11POS, FLOATPOS,
|
||||
FULLSCREENPOS, PINNEDPOS, FULLSCREENSTATEPOS, WORKSPACEPOS, FOCUSPOS, ONWORKSPACEPOS};
|
||||
if (checkPos.size() == 1 && checkPos.contains(std::string::npos)) {
|
||||
Debug::log(ERR, "Invalid rulev2 syntax: {}", VALUE);
|
||||
return "Invalid rulev2 syntax: " + VALUE;
|
||||
|
@ -2243,6 +2419,8 @@ std::optional<std::string> CConfigManager::handleWindowRuleV2(const std::string&
|
|||
min = FULLSCREENPOS;
|
||||
if (PINNEDPOS > pos && PINNEDPOS < min)
|
||||
min = PINNEDPOS;
|
||||
if (FULLSCREENSTATEPOS > pos && FULLSCREENSTATEPOS < min)
|
||||
min = FULLSCREENSTATEPOS;
|
||||
if (ONWORKSPACEPOS > pos && ONWORKSPACEPOS < min)
|
||||
min = ONWORKSPACEPOS;
|
||||
if (WORKSPACEPOS > pos && WORKSPACEPOS < min)
|
||||
|
@ -2287,6 +2465,9 @@ std::optional<std::string> CConfigManager::handleWindowRuleV2(const std::string&
|
|||
if (PINNEDPOS != std::string::npos)
|
||||
rule.bPinned = extract(PINNEDPOS + 7) == "1" ? 1 : 0;
|
||||
|
||||
if (FULLSCREENSTATEPOS != std::string::npos)
|
||||
rule.szFullscreenState = extract(FULLSCREENSTATEPOS + 16);
|
||||
|
||||
if (WORKSPACEPOS != std::string::npos)
|
||||
rule.szWorkspace = extract(WORKSPACEPOS + 10);
|
||||
|
||||
|
@ -2328,6 +2509,9 @@ std::optional<std::string> CConfigManager::handleWindowRuleV2(const std::string&
|
|||
if (rule.bPinned != -1 && rule.bPinned != other.bPinned)
|
||||
return false;
|
||||
|
||||
if (!rule.szFullscreenState.empty() && rule.szFullscreenState != other.szFullscreenState)
|
||||
return false;
|
||||
|
||||
if (!rule.szWorkspace.empty() && rule.szWorkspace != other.szWorkspace)
|
||||
return false;
|
||||
|
||||
|
@ -2359,9 +2543,9 @@ void CConfigManager::updateBlurredLS(const std::string& name, const bool forceBl
|
|||
matchName = matchName.substr(8);
|
||||
}
|
||||
|
||||
for (auto& m : g_pCompositor->m_vMonitors) {
|
||||
for (auto& lsl : m->m_aLayerSurfaceLayers) {
|
||||
for (auto& ls : lsl) {
|
||||
for (auto const& m : g_pCompositor->m_vMonitors) {
|
||||
for (auto const& lsl : m->m_aLayerSurfaceLayers) {
|
||||
for (auto const& ls : lsl) {
|
||||
if (BYADDRESS) {
|
||||
if (std::format("0x{:x}", (uintptr_t)ls.get()) == matchName)
|
||||
ls->forceBlur = forceBlur;
|
||||
|
@ -2414,7 +2598,7 @@ std::optional<std::string> CConfigManager::handleWorkspaceRules(const std::strin
|
|||
// }
|
||||
|
||||
const static std::string ruleOnCreatedEmpty = "on-created-empty:";
|
||||
const static int ruleOnCreatedEmptyLen = ruleOnCreatedEmpty.length();
|
||||
const static auto ruleOnCreatedEmptyLen = ruleOnCreatedEmpty.length();
|
||||
|
||||
auto assignRule = [&](std::string rule) -> std::optional<std::string> {
|
||||
size_t delim = std::string::npos;
|
||||
|
@ -2470,7 +2654,7 @@ std::optional<std::string> CConfigManager::handleWorkspaceRules(const std::strin
|
|||
};
|
||||
|
||||
CVarList rulesList{rules, 0, ',', true};
|
||||
for (auto& r : rulesList) {
|
||||
for (auto const& r : rulesList) {
|
||||
const auto R = assignRule(r);
|
||||
if (R.has_value())
|
||||
return R;
|
||||
|
@ -2586,3 +2770,60 @@ std::optional<std::string> CConfigManager::handlePlugin(const std::string& comma
|
|||
|
||||
return {};
|
||||
}
|
||||
|
||||
const std::vector<SConfigOptionDescription>& CConfigManager::getAllDescriptions() {
|
||||
return CONFIG_OPTIONS;
|
||||
}
|
||||
|
||||
std::string SConfigOptionDescription::jsonify() const {
|
||||
auto parseData = [this]() -> std::string {
|
||||
return std::visit(
|
||||
[](auto&& val) {
|
||||
using T = std::decay_t<decltype(val)>;
|
||||
if constexpr (std::is_same_v<T, SStringData>) {
|
||||
return std::format(R"#( "value": "{}")#", val.value);
|
||||
} else if constexpr (std::is_same_v<T, SRangeData>) {
|
||||
return std::format(R"#( "value": {},
|
||||
"min": {},
|
||||
"max": {})#",
|
||||
val.value, val.min, val.max);
|
||||
} else if constexpr (std::is_same_v<T, SFloatData>) {
|
||||
return std::format(R"#( "value": {},
|
||||
"min": {},
|
||||
"max": {})#",
|
||||
val.value, val.min, val.max);
|
||||
} else if constexpr (std::is_same_v<T, SColorData>) {
|
||||
return std::format(R"#( "value": {})#", val.color.getAsHex());
|
||||
} else if constexpr (std::is_same_v<T, SBoolData>) {
|
||||
return std::format(R"#( "value": {})#", val.value);
|
||||
} else if constexpr (std::is_same_v<T, SChoiceData>) {
|
||||
return std::format(R"#( "value": {})#", val.choices);
|
||||
} else if constexpr (std::is_same_v<T, SVectorData>) {
|
||||
return std::format(R"#( "x": {},
|
||||
"y": {},
|
||||
"min_x": {},
|
||||
"min_y": {},
|
||||
"max_x": {},
|
||||
"max_y": {})#",
|
||||
val.vec.x, val.vec.y, val.min.x, val.min.y, val.max.x, val.max.y);
|
||||
} else if constexpr (std::is_same_v<T, SGradientData>) {
|
||||
return std::format(R"#( "value": "{}")#", val.gradient);
|
||||
}
|
||||
return std::string{""};
|
||||
},
|
||||
data);
|
||||
};
|
||||
|
||||
std::string json = std::format(R"#({{
|
||||
"value": "{}",
|
||||
"description": "{}",
|
||||
"type": {},
|
||||
"flags": {},
|
||||
"data": {{
|
||||
{}
|
||||
}}
|
||||
}})#",
|
||||
value, description, (uint16_t)type, (uint32_t)flags, parseData());
|
||||
|
||||
return json;
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include "../debug/Log.hpp"
|
||||
#include <unordered_map>
|
||||
#include "../defines.hpp"
|
||||
#include <variant>
|
||||
#include <vector>
|
||||
#include <deque>
|
||||
#include <algorithm>
|
||||
|
@ -33,7 +34,7 @@ struct SWorkspaceRule {
|
|||
std::string monitor = "";
|
||||
std::string workspaceString = "";
|
||||
std::string workspaceName = "";
|
||||
int workspaceId = -1;
|
||||
WORKSPACEID workspaceId = -1;
|
||||
bool isDefault = false;
|
||||
bool isPersistent = false;
|
||||
std::optional<CCssGapData> gapsIn;
|
||||
|
@ -83,6 +84,70 @@ struct SExecRequestedRule {
|
|||
uint64_t iPid = 0;
|
||||
};
|
||||
|
||||
enum eConfigOptionType : uint16_t {
|
||||
CONFIG_OPTION_BOOL = 0,
|
||||
CONFIG_OPTION_INT = 1, /* e.g. 0/1/2*/
|
||||
CONFIG_OPTION_FLOAT = 2,
|
||||
CONFIG_OPTION_STRING_SHORT = 3, /* e.g. "auto" */
|
||||
CONFIG_OPTION_STRING_LONG = 4, /* e.g. a command */
|
||||
CONFIG_OPTION_COLOR = 5,
|
||||
CONFIG_OPTION_CHOICE = 6, /* e.g. "one", "two", "three" */
|
||||
CONFIG_OPTION_GRADIENT = 7,
|
||||
CONFIG_OPTION_VECTOR = 8,
|
||||
};
|
||||
|
||||
enum eConfigOptionFlags : uint32_t {
|
||||
CONFIG_OPTION_FLAG_PERCENTAGE = (1 << 0),
|
||||
};
|
||||
|
||||
struct SConfigOptionDescription {
|
||||
|
||||
struct SBoolData {
|
||||
bool value = false;
|
||||
};
|
||||
|
||||
struct SRangeData {
|
||||
int value = 0, min = 0, max = 2;
|
||||
};
|
||||
|
||||
struct SFloatData {
|
||||
float value = 0, min = 0, max = 100;
|
||||
};
|
||||
|
||||
struct SStringData {
|
||||
std::string value;
|
||||
};
|
||||
|
||||
struct SColorData {
|
||||
CColor color;
|
||||
};
|
||||
|
||||
struct SChoiceData {
|
||||
int firstIndex = 0;
|
||||
std::string choices; // comma-separated
|
||||
};
|
||||
|
||||
struct SGradientData {
|
||||
std::string gradient;
|
||||
};
|
||||
|
||||
struct SVectorData {
|
||||
Vector2D vec, min, max;
|
||||
};
|
||||
|
||||
std::string value; // e.g. general:gaps_in
|
||||
std::string description;
|
||||
std::string specialCategory; // if value is special (e.g. device:abc) value will be abc and special device
|
||||
bool specialKey = false;
|
||||
eConfigOptionType type = CONFIG_OPTION_BOOL;
|
||||
uint32_t flags = 0; // eConfigOptionFlags
|
||||
|
||||
std::string jsonify() const;
|
||||
|
||||
//
|
||||
std::variant<SBoolData, SRangeData, SFloatData, SStringData, SColorData, SChoiceData, SGradientData, SVectorData> data;
|
||||
};
|
||||
|
||||
class CConfigManager {
|
||||
public:
|
||||
CConfigManager();
|
||||
|
@ -104,7 +169,7 @@ class CConfigManager {
|
|||
static std::string getMainConfigPath();
|
||||
const std::string getConfigString();
|
||||
|
||||
SMonitorRule getMonitorRuleFor(const CMonitor&);
|
||||
SMonitorRule getMonitorRuleFor(const SP<CMonitor>);
|
||||
SWorkspaceRule getWorkspaceRuleFor(PHLWORKSPACE workspace);
|
||||
std::string getDefaultWorkspaceFor(const std::string&);
|
||||
|
||||
|
@ -115,6 +180,8 @@ class CConfigManager {
|
|||
std::vector<SWindowRule> getMatchingRules(PHLWINDOW, bool dynamic = true, bool shadowExec = false);
|
||||
std::vector<SLayerRule> getMatchingRules(PHLLS);
|
||||
|
||||
const std::vector<SConfigOptionDescription>& getAllDescriptions();
|
||||
|
||||
std::unordered_map<std::string, SMonitorAdditionalReservedArea> m_mAdditionalReservedAreas;
|
||||
|
||||
std::unordered_map<std::string, SAnimationPropertyConfig> getAnimationConfig();
|
||||
|
@ -125,6 +192,7 @@ class CConfigManager {
|
|||
|
||||
// no-op when done.
|
||||
void dispatchExecOnce();
|
||||
void dispatchExecShutdown();
|
||||
|
||||
void performMonitorReload();
|
||||
void appendMonitorRule(const SMonitorRule&);
|
||||
|
@ -146,6 +214,7 @@ class CConfigManager {
|
|||
// keywords
|
||||
std::optional<std::string> handleRawExec(const std::string&, const std::string&);
|
||||
std::optional<std::string> handleExecOnce(const std::string&, const std::string&);
|
||||
std::optional<std::string> handleExecShutdown(const std::string&, const std::string&);
|
||||
std::optional<std::string> handleMonitor(const std::string&, const std::string&);
|
||||
std::optional<std::string> handleBind(const std::string&, const std::string&);
|
||||
std::optional<std::string> handleUnbind(const std::string&, const std::string&);
|
||||
|
@ -222,6 +291,7 @@ class CConfigManager {
|
|||
bool firstExecDispatched = false;
|
||||
bool m_bManualCrashInitiated = false;
|
||||
std::deque<std::string> firstExecRequests;
|
||||
std::deque<std::string> finalExecRequests;
|
||||
|
||||
std::vector<std::pair<std::string, std::string>> m_vFailedPluginConfigValues; // for plugin values of unloaded plugins
|
||||
std::string m_szConfigErrors = "";
|
||||
|
|
|
@ -130,6 +130,13 @@ animations {
|
|||
animation = workspaces, 1, 6, default
|
||||
}
|
||||
|
||||
# Ref https://wiki.hyprland.org/Configuring/Workspace-Rules/
|
||||
# "Smart gaps" / "No gaps when only"
|
||||
# uncomment all three if you wish to use that.
|
||||
# workspace = w[t1], gapsout:0, gapsin:0, border: 0, rounding:0
|
||||
# workspace = w[tg1], gapsout:0, gapsin:0, border: 0, rounding:0
|
||||
# workspace = f[1], gapsout:0, gapsin:0, border: 0, rounding:0
|
||||
|
||||
# See https://wiki.hyprland.org/Configuring/Dwindle-Layout/ for more
|
||||
dwindle {
|
||||
pseudotile = true # Master switch for pseudotiling. Enabling is bound to mainMod + P in the keybinds section below
|
||||
|
@ -182,9 +189,9 @@ device {
|
|||
}
|
||||
|
||||
|
||||
####################
|
||||
### KEYBINDINGSS ###
|
||||
####################
|
||||
###################
|
||||
### KEYBINDINGS ###
|
||||
###################
|
||||
|
||||
# See https://wiki.hyprland.org/Configuring/Keywords/
|
||||
$mainMod = SUPER # Sets "Windows" key as main modifier
|
||||
|
@ -241,6 +248,19 @@ bind = $mainMod, mouse_up, workspace, e-1
|
|||
bindm = $mainMod, mouse:272, movewindow
|
||||
bindm = $mainMod, mouse:273, resizewindow
|
||||
|
||||
# Laptop multimedia keys for volume and LCD brightness
|
||||
bindel = ,XF86AudioRaiseVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%+
|
||||
bindel = ,XF86AudioLowerVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%-
|
||||
bindel = ,XF86AudioMute, exec, wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle
|
||||
bindel = ,XF86AudioMicMute, exec, wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle
|
||||
bindel = ,XF86MonBrightnessUp, exec, brightnessctl s 10%+
|
||||
bindel = ,XF86MonBrightnessDown, exec, brightnessctl s 10%-
|
||||
|
||||
# Requires playerctl
|
||||
bindl = , XF86AudioNext, exec, playerctl next
|
||||
bindl = , XF86AudioPause, exec, playerctl play-pause
|
||||
bindl = , XF86AudioPlay, exec, playerctl play-pause
|
||||
bindl = , XF86AudioPrev, exec, playerctl previous
|
||||
|
||||
##############################
|
||||
### WINDOWS AND WORKSPACES ###
|
||||
|
@ -255,5 +275,9 @@ bindm = $mainMod, mouse:273, resizewindow
|
|||
# Example windowrule v2
|
||||
# windowrulev2 = float,class:^(kitty)$,title:^(kitty)$
|
||||
|
||||
windowrulev2 = suppressevent maximize, class:.* # You'll probably like this.
|
||||
# Ignore maximize requests from apps. You'll probably like this.
|
||||
windowrulev2 = suppressevent maximize, class:.*
|
||||
|
||||
# Fix some dragging issues with XWayland
|
||||
windowrulev2 = nofocus,class:^$,title:^$,xwayland:1,floating:1,fullscreen:0,pinned:0
|
||||
)#";
|
||||
|
|
|
@ -86,7 +86,7 @@ void CrashReporter::createAndSaveCrash(int sig) {
|
|||
stderr.flush();
|
||||
}
|
||||
|
||||
reportFd = open(reportPath.get_str(), O_WRONLY | O_CREAT, S_IRWXU);
|
||||
reportFd = open(reportPath.get_str(), O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
|
||||
if (reportFd < 0) {
|
||||
exit_with_error("Failed to open crash report path for writing");
|
||||
}
|
||||
|
|
|
@ -57,7 +57,7 @@ static std::string formatToString(uint32_t drmFormat) {
|
|||
static std::string availableModesForOutput(CMonitor* pMonitor, eHyprCtlOutputFormat format) {
|
||||
std::string result;
|
||||
|
||||
for (auto& m : pMonitor->output->modes) {
|
||||
for (auto const& m : pMonitor->output->modes) {
|
||||
if (format == FORMAT_NORMAL)
|
||||
result += std::format("{}x{}@{:.2f}Hz ", m->pixelSize.x, m->pixelSize.y, m->refreshRate / 1000.0);
|
||||
else
|
||||
|
@ -71,7 +71,7 @@ static std::string availableModesForOutput(CMonitor* pMonitor, eHyprCtlOutputFor
|
|||
|
||||
std::string CHyprCtl::getMonitorData(Hyprutils::Memory::CSharedPointer<CMonitor> m, eHyprCtlOutputFormat format) {
|
||||
std::string result;
|
||||
if (!m->output || m->ID == -1ull)
|
||||
if (!m->output || m->ID == -1)
|
||||
return "";
|
||||
|
||||
if (format == eHyprCtlOutputFormat::FORMAT_JSON) {
|
||||
|
@ -103,6 +103,7 @@ std::string CHyprCtl::getMonitorData(Hyprutils::Memory::CSharedPointer<CMonitor>
|
|||
"focused": {},
|
||||
"dpmsStatus": {},
|
||||
"vrr": {},
|
||||
"solitary": "{:x}",
|
||||
"activelyTearing": {},
|
||||
"disabled": {},
|
||||
"currentFormat": "{}",
|
||||
|
@ -114,19 +115,20 @@ std::string CHyprCtl::getMonitorData(Hyprutils::Memory::CSharedPointer<CMonitor>
|
|||
m->activeWorkspaceID(), (!m->activeWorkspace ? "" : escapeJSONStrings(m->activeWorkspace->m_szName)), m->activeSpecialWorkspaceID(),
|
||||
escapeJSONStrings(m->activeSpecialWorkspace ? m->activeSpecialWorkspace->m_szName : ""), (int)m->vecReservedTopLeft.x, (int)m->vecReservedTopLeft.y,
|
||||
(int)m->vecReservedBottomRight.x, (int)m->vecReservedBottomRight.y, m->scale, (int)m->transform, (m == g_pCompositor->m_pLastMonitor ? "true" : "false"),
|
||||
(m->dpmsStatus ? "true" : "false"), (m->output->state->state().adaptiveSync ? "true" : "false"), (m->tearingState.activelyTearing ? "true" : "false"),
|
||||
(m->m_bEnabled ? "false" : "true"), formatToString(m->output->state->state().drmFormat), availableModesForOutput(m.get(), format));
|
||||
(m->dpmsStatus ? "true" : "false"), (m->output->state->state().adaptiveSync ? "true" : "false"), (uint64_t)m->solitaryClient.get(),
|
||||
(m->tearingState.activelyTearing ? "true" : "false"), (m->m_bEnabled ? "false" : "true"), formatToString(m->output->state->state().drmFormat),
|
||||
availableModesForOutput(m.get(), format));
|
||||
|
||||
} else {
|
||||
result += std::format("Monitor {} (ID {}):\n\t{}x{}@{:.5f} at {}x{}\n\tdescription: {}\n\tmake: {}\n\tmodel: {}\n\tserial: {}\n\tactive workspace: {} ({})\n\t"
|
||||
"special workspace: {} ({})\n\treserved: {} {} {} {}\n\tscale: {:.2f}\n\ttransform: {}\n\tfocused: {}\n\t"
|
||||
"dpmsStatus: {}\n\tvrr: {}\n\tactivelyTearing: {}\n\tdisabled: {}\n\tcurrentFormat: {}\n\tavailableModes: {}\n\n",
|
||||
"dpmsStatus: {}\n\tvrr: {}\n\tsolitary: {:x}\n\tactivelyTearing: {}\n\tdisabled: {}\n\tcurrentFormat: {}\n\tavailableModes: {}\n\n",
|
||||
m->szName, m->ID, (int)m->vecPixelSize.x, (int)m->vecPixelSize.y, m->refreshRate, (int)m->vecPosition.x, (int)m->vecPosition.y, m->szShortDescription,
|
||||
m->output->make, m->output->model, m->output->serial, m->activeWorkspaceID(), (!m->activeWorkspace ? "" : m->activeWorkspace->m_szName),
|
||||
m->activeSpecialWorkspaceID(), (m->activeSpecialWorkspace ? m->activeSpecialWorkspace->m_szName : ""), (int)m->vecReservedTopLeft.x,
|
||||
(int)m->vecReservedTopLeft.y, (int)m->vecReservedBottomRight.x, (int)m->vecReservedBottomRight.y, m->scale, (int)m->transform,
|
||||
(m == g_pCompositor->m_pLastMonitor ? "yes" : "no"), (int)m->dpmsStatus, m->output->state->state().adaptiveSync, m->tearingState.activelyTearing,
|
||||
!m->m_bEnabled, formatToString(m->output->state->state().drmFormat), availableModesForOutput(m.get(), format));
|
||||
(m == g_pCompositor->m_pLastMonitor ? "yes" : "no"), (int)m->dpmsStatus, m->output->state->state().adaptiveSync, (uint64_t)m->solitaryClient.get(),
|
||||
m->tearingState.activelyTearing, !m->m_bEnabled, formatToString(m->output->state->state().drmFormat), availableModesForOutput(m.get(), format));
|
||||
}
|
||||
|
||||
return result;
|
||||
|
@ -146,7 +148,7 @@ std::string monitorsRequest(eHyprCtlOutputFormat format, std::string request) {
|
|||
if (format == eHyprCtlOutputFormat::FORMAT_JSON) {
|
||||
result += "[";
|
||||
|
||||
for (auto& m : allMonitors ? g_pCompositor->m_vRealMonitors : g_pCompositor->m_vMonitors) {
|
||||
for (auto const& m : allMonitors ? g_pCompositor->m_vRealMonitors : g_pCompositor->m_vMonitors) {
|
||||
result += CHyprCtl::getMonitorData(m, format);
|
||||
}
|
||||
|
||||
|
@ -154,20 +156,11 @@ std::string monitorsRequest(eHyprCtlOutputFormat format, std::string request) {
|
|||
|
||||
result += "]";
|
||||
} else {
|
||||
for (auto& m : allMonitors ? g_pCompositor->m_vRealMonitors : g_pCompositor->m_vMonitors) {
|
||||
if (!m->output || m->ID == -1ull)
|
||||
for (auto const& m : allMonitors ? g_pCompositor->m_vRealMonitors : g_pCompositor->m_vMonitors) {
|
||||
if (!m->output || m->ID == -1)
|
||||
continue;
|
||||
|
||||
result +=
|
||||
std::format("Monitor {} (ID {}):\n\t{}x{}@{:.5f} at {}x{}\n\tdescription: {}\n\tmake: {}\n\tmodel: {}\n\tserial: {}\n\tactive workspace: {} ({})\n\t"
|
||||
"special workspace: {} ({})\n\treserved: {} {} {} {}\n\tscale: {:.2f}\n\ttransform: {}\n\tfocused: {}\n\t"
|
||||
"dpmsStatus: {}\n\tvrr: {}\n\tactivelyTearing: {}\n\tdisabled: {}\n\tcurrentFormat: {}\n\tavailableModes: {}\n\n",
|
||||
m->szName, m->ID, (int)m->vecPixelSize.x, (int)m->vecPixelSize.y, m->refreshRate, (int)m->vecPosition.x, (int)m->vecPosition.y, m->szShortDescription,
|
||||
m->output->make, m->output->model, m->output->serial, m->activeWorkspaceID(), (!m->activeWorkspace ? "" : m->activeWorkspace->m_szName),
|
||||
m->activeSpecialWorkspaceID(), (m->activeSpecialWorkspace ? m->activeSpecialWorkspace->m_szName : ""), (int)m->vecReservedTopLeft.x,
|
||||
(int)m->vecReservedTopLeft.y, (int)m->vecReservedBottomRight.x, (int)m->vecReservedBottomRight.y, m->scale, (int)m->transform,
|
||||
(m == g_pCompositor->m_pLastMonitor ? "yes" : "no"), (int)m->dpmsStatus, (int)(m->output->state ? m->output->state->state().adaptiveSync : false),
|
||||
m->tearingState.activelyTearing, !m->m_bEnabled, formatToString(m->output->state->state().drmFormat), availableModesForOutput(m.get(), format));
|
||||
result += CHyprCtl::getMonitorData(m, format);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -272,7 +265,7 @@ std::string clientsRequest(eHyprCtlOutputFormat format, std::string request) {
|
|||
if (format == eHyprCtlOutputFormat::FORMAT_JSON) {
|
||||
result += "[";
|
||||
|
||||
for (auto& w : g_pCompositor->m_vWindows) {
|
||||
for (auto const& w : g_pCompositor->m_vWindows) {
|
||||
if (!w->m_bIsMapped && !g_pHyprCtl->m_sCurrentRequestParams.all)
|
||||
continue;
|
||||
|
||||
|
@ -283,7 +276,7 @@ std::string clientsRequest(eHyprCtlOutputFormat format, std::string request) {
|
|||
|
||||
result += "]";
|
||||
} else {
|
||||
for (auto& w : g_pCompositor->m_vWindows) {
|
||||
for (auto const& w : g_pCompositor->m_vWindows) {
|
||||
if (!w->m_bIsMapped && !g_pHyprCtl->m_sCurrentRequestParams.all)
|
||||
continue;
|
||||
|
||||
|
@ -334,11 +327,13 @@ static std::string getWorkspaceRuleData(const SWorkspaceRule& r, eHyprCtlOutputF
|
|||
const std::string rounding = (bool)(r.noRounding) ? std::format(",\n \"rounding\": {}", boolToString(!r.noRounding.value())) : "";
|
||||
const std::string decorate = (bool)(r.decorate) ? std::format(",\n \"decorate\": {}", boolToString(r.decorate.value())) : "";
|
||||
const std::string shadow = (bool)(r.noShadow) ? std::format(",\n \"shadow\": {}", boolToString(!r.noShadow.value())) : "";
|
||||
const std::string defaultName = r.defaultName.has_value() ? std::format(",\n \"defaultName\": \"{}\"", escapeJSONStrings(r.defaultName.value())) : "";
|
||||
|
||||
std::string result = std::format(R"#({{
|
||||
"workspaceString": "{}"{}{}{}{}{}{}{}{}
|
||||
std::string result =
|
||||
std::format(R"#({{
|
||||
"workspaceString": "{}"{}{}{}{}{}{}{}{}{}{}{}
|
||||
}})#",
|
||||
escapeJSONStrings(r.workspaceString), monitor, default_, persistent, gapsIn, gapsOut, borderSize, border, rounding, decorate, shadow);
|
||||
escapeJSONStrings(r.workspaceString), monitor, default_, persistent, gapsIn, gapsOut, borderSize, border, rounding, decorate, shadow, defaultName);
|
||||
|
||||
return result;
|
||||
} else {
|
||||
|
@ -356,9 +351,10 @@ static std::string getWorkspaceRuleData(const SWorkspaceRule& r, eHyprCtlOutputF
|
|||
const std::string rounding = std::format("\trounding: {}\n", (bool)(r.noRounding) ? boolToString(!r.noRounding.value()) : "<unset>");
|
||||
const std::string decorate = std::format("\tdecorate: {}\n", (bool)(r.decorate) ? boolToString(r.decorate.value()) : "<unset>");
|
||||
const std::string shadow = std::format("\tshadow: {}\n", (bool)(r.noShadow) ? boolToString(!r.noShadow.value()) : "<unset>");
|
||||
const std::string defaultName = std::format("\tdefaultName: {}\n", r.defaultName.value_or("<unset>"));
|
||||
|
||||
std::string result = std::format("Workspace rule {}:\n{}{}{}{}{}{}{}{}{}{}\n", escapeJSONStrings(r.workspaceString), monitor, default_, persistent, gapsIn, gapsOut,
|
||||
borderSize, border, rounding, decorate, shadow);
|
||||
std::string result = std::format("Workspace rule {}:\n{}{}{}{}{}{}{}{}{}{}{}\n", escapeJSONStrings(r.workspaceString), monitor, default_, persistent, gapsIn, gapsOut,
|
||||
borderSize, border, rounding, decorate, shadow, defaultName);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -381,7 +377,7 @@ std::string workspacesRequest(eHyprCtlOutputFormat format, std::string request)
|
|||
|
||||
if (format == eHyprCtlOutputFormat::FORMAT_JSON) {
|
||||
result += "[";
|
||||
for (auto& w : g_pCompositor->m_vWorkspaces) {
|
||||
for (auto const& w : g_pCompositor->m_vWorkspaces) {
|
||||
result += CHyprCtl::getWorkspaceData(w, format);
|
||||
result += ",";
|
||||
}
|
||||
|
@ -389,7 +385,7 @@ std::string workspacesRequest(eHyprCtlOutputFormat format, std::string request)
|
|||
trimTrailingComma(result);
|
||||
result += "]";
|
||||
} else {
|
||||
for (auto& w : g_pCompositor->m_vWorkspaces) {
|
||||
for (auto const& w : g_pCompositor->m_vWorkspaces) {
|
||||
result += CHyprCtl::getWorkspaceData(w, format);
|
||||
}
|
||||
}
|
||||
|
@ -401,7 +397,7 @@ std::string workspaceRulesRequest(eHyprCtlOutputFormat format, std::string reque
|
|||
std::string result = "";
|
||||
if (format == eHyprCtlOutputFormat::FORMAT_JSON) {
|
||||
result += "[";
|
||||
for (auto& r : g_pConfigManager->getAllWorkspaceRules()) {
|
||||
for (auto const& r : g_pConfigManager->getAllWorkspaceRules()) {
|
||||
result += getWorkspaceRuleData(r, format);
|
||||
result += ",";
|
||||
}
|
||||
|
@ -409,7 +405,7 @@ std::string workspaceRulesRequest(eHyprCtlOutputFormat format, std::string reque
|
|||
trimTrailingComma(result);
|
||||
result += "]";
|
||||
} else {
|
||||
for (auto& r : g_pConfigManager->getAllWorkspaceRules()) {
|
||||
for (auto const& r : g_pConfigManager->getAllWorkspaceRules()) {
|
||||
result += getWorkspaceRuleData(r, format);
|
||||
}
|
||||
}
|
||||
|
@ -437,7 +433,7 @@ std::string layersRequest(eHyprCtlOutputFormat format, std::string request) {
|
|||
if (format == eHyprCtlOutputFormat::FORMAT_JSON) {
|
||||
result += "{\n";
|
||||
|
||||
for (auto& mon : g_pCompositor->m_vMonitors) {
|
||||
for (auto const& mon : g_pCompositor->m_vMonitors) {
|
||||
result += std::format(
|
||||
R"#("{}": {{
|
||||
"levels": {{
|
||||
|
@ -445,13 +441,13 @@ std::string layersRequest(eHyprCtlOutputFormat format, std::string request) {
|
|||
escapeJSONStrings(mon->szName));
|
||||
|
||||
int layerLevel = 0;
|
||||
for (auto& level : mon->m_aLayerSurfaceLayers) {
|
||||
for (auto const& level : mon->m_aLayerSurfaceLayers) {
|
||||
result += std::format(
|
||||
R"#(
|
||||
"{}": [
|
||||
)#",
|
||||
layerLevel);
|
||||
for (auto& layer : level) {
|
||||
for (auto const& layer : level) {
|
||||
result += std::format(
|
||||
R"#( {{
|
||||
"address": "0x{:x}",
|
||||
|
@ -484,14 +480,14 @@ std::string layersRequest(eHyprCtlOutputFormat format, std::string request) {
|
|||
result += "\n}\n";
|
||||
|
||||
} else {
|
||||
for (auto& mon : g_pCompositor->m_vMonitors) {
|
||||
for (auto const& mon : g_pCompositor->m_vMonitors) {
|
||||
result += std::format("Monitor {}:\n", mon->szName);
|
||||
int layerLevel = 0;
|
||||
static const std::array<std::string, 4> levelNames = {"background", "bottom", "top", "overlay"};
|
||||
for (auto& level : mon->m_aLayerSurfaceLayers) {
|
||||
for (auto const& level : mon->m_aLayerSurfaceLayers) {
|
||||
result += std::format("\tLayer level {} ({}):\n", layerLevel, levelNames[layerLevel]);
|
||||
|
||||
for (auto& layer : level) {
|
||||
for (auto const& layer : level) {
|
||||
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);
|
||||
}
|
||||
|
@ -510,7 +506,7 @@ std::string layoutsRequest(eHyprCtlOutputFormat format, std::string request) {
|
|||
if (format == eHyprCtlOutputFormat::FORMAT_JSON) {
|
||||
result += "[";
|
||||
|
||||
for (auto& m : g_pLayoutManager->getAllLayoutNames()) {
|
||||
for (auto const& m : g_pLayoutManager->getAllLayoutNames()) {
|
||||
result += std::format(
|
||||
R"#(
|
||||
"{}",)#",
|
||||
|
@ -520,7 +516,7 @@ std::string layoutsRequest(eHyprCtlOutputFormat format, std::string request) {
|
|||
|
||||
result += "\n]\n";
|
||||
} else {
|
||||
for (auto& m : g_pLayoutManager->getAllLayoutNames()) {
|
||||
for (auto const& m : g_pLayoutManager->getAllLayoutNames()) {
|
||||
result += std::format("{}\n", m);
|
||||
}
|
||||
}
|
||||
|
@ -557,7 +553,7 @@ std::string devicesRequest(eHyprCtlOutputFormat format, std::string request) {
|
|||
result += "{\n";
|
||||
result += "\"mice\": [\n";
|
||||
|
||||
for (auto& m : g_pInputManager->m_vPointers) {
|
||||
for (auto const& m : g_pInputManager->m_vPointers) {
|
||||
result += std::format(
|
||||
R"#( {{
|
||||
"address": "0x{:x}",
|
||||
|
@ -572,7 +568,7 @@ std::string devicesRequest(eHyprCtlOutputFormat format, std::string request) {
|
|||
result += "\n],\n";
|
||||
|
||||
result += "\"keyboards\": [\n";
|
||||
for (auto& k : g_pInputManager->m_vKeyboards) {
|
||||
for (auto const& k : g_pInputManager->m_vKeyboards) {
|
||||
const auto KM = k->getActiveLayout();
|
||||
result += std::format(
|
||||
R"#( {{
|
||||
|
@ -596,7 +592,7 @@ std::string devicesRequest(eHyprCtlOutputFormat format, std::string request) {
|
|||
|
||||
result += "\"tablets\": [\n";
|
||||
|
||||
for (auto& d : g_pInputManager->m_vTabletPads) {
|
||||
for (auto const& d : g_pInputManager->m_vTabletPads) {
|
||||
result += std::format(
|
||||
R"#( {{
|
||||
"address": "0x{:x}",
|
||||
|
@ -609,7 +605,7 @@ std::string devicesRequest(eHyprCtlOutputFormat format, std::string request) {
|
|||
(uintptr_t)d.get(), (uintptr_t)d->parent.get(), escapeJSONStrings(d->parent ? d->parent->hlName : ""));
|
||||
}
|
||||
|
||||
for (auto& d : g_pInputManager->m_vTablets) {
|
||||
for (auto const& d : g_pInputManager->m_vTablets) {
|
||||
result += std::format(
|
||||
R"#( {{
|
||||
"address": "0x{:x}",
|
||||
|
@ -618,7 +614,7 @@ std::string devicesRequest(eHyprCtlOutputFormat format, std::string request) {
|
|||
(uintptr_t)d.get(), escapeJSONStrings(d->hlName));
|
||||
}
|
||||
|
||||
for (auto& d : g_pInputManager->m_vTabletTools) {
|
||||
for (auto const& d : g_pInputManager->m_vTabletTools) {
|
||||
result += std::format(
|
||||
R"#( {{
|
||||
"address": "0x{:x}",
|
||||
|
@ -632,7 +628,7 @@ std::string devicesRequest(eHyprCtlOutputFormat format, std::string request) {
|
|||
|
||||
result += "\"touch\": [\n";
|
||||
|
||||
for (auto& d : g_pInputManager->m_vTouches) {
|
||||
for (auto const& d : g_pInputManager->m_vTouches) {
|
||||
result += std::format(
|
||||
R"#( {{
|
||||
"address": "0x{:x}",
|
||||
|
@ -646,7 +642,7 @@ std::string devicesRequest(eHyprCtlOutputFormat format, std::string request) {
|
|||
|
||||
result += "\"switches\": [\n";
|
||||
|
||||
for (auto& d : g_pInputManager->m_lSwitches) {
|
||||
for (auto const& d : g_pInputManager->m_lSwitches) {
|
||||
result += std::format(
|
||||
R"#( {{
|
||||
"address": "0x{:x}",
|
||||
|
@ -663,14 +659,14 @@ std::string devicesRequest(eHyprCtlOutputFormat format, std::string request) {
|
|||
} else {
|
||||
result += "mice:\n";
|
||||
|
||||
for (auto& m : g_pInputManager->m_vPointers) {
|
||||
for (auto const& m : g_pInputManager->m_vPointers) {
|
||||
result += std::format("\tMouse at {:x}:\n\t\t{}\n\t\t\tdefault speed: {:.5f}\n", (uintptr_t)m.get(), m->hlName,
|
||||
(m->aq() && m->aq()->getLibinputHandle() ? libinput_device_config_accel_get_default_speed(m->aq()->getLibinputHandle()) : 0.f));
|
||||
}
|
||||
|
||||
result += "\n\nKeyboards:\n";
|
||||
|
||||
for (auto& k : g_pInputManager->m_vKeyboards) {
|
||||
for (auto const& k : g_pInputManager->m_vKeyboards) {
|
||||
const auto KM = k->getActiveLayout();
|
||||
result += std::format("\tKeyboard at {:x}:\n\t\t{}\n\t\t\trules: r \"{}\", m \"{}\", l \"{}\", v \"{}\", o \"{}\"\n\t\t\tactive keymap: {}\n\t\t\tmain: {}\n",
|
||||
(uintptr_t)k.get(), k->hlName, k->currentRules.rules, k->currentRules.model, k->currentRules.layout, k->currentRules.variant,
|
||||
|
@ -679,27 +675,27 @@ std::string devicesRequest(eHyprCtlOutputFormat format, std::string request) {
|
|||
|
||||
result += "\n\nTablets:\n";
|
||||
|
||||
for (auto& d : g_pInputManager->m_vTabletPads) {
|
||||
for (auto const& d : g_pInputManager->m_vTabletPads) {
|
||||
result += std::format("\tTablet Pad at {:x} (belongs to {:x} -> {})\n", (uintptr_t)d.get(), (uintptr_t)d->parent.get(), d->parent ? d->parent->hlName : "");
|
||||
}
|
||||
|
||||
for (auto& d : g_pInputManager->m_vTablets) {
|
||||
for (auto const& d : g_pInputManager->m_vTablets) {
|
||||
result += std::format("\tTablet at {:x}:\n\t\t{}\n\t\t\tsize: {}x{}mm\n", (uintptr_t)d.get(), d->hlName, d->aq()->physicalSize.x, d->aq()->physicalSize.y);
|
||||
}
|
||||
|
||||
for (auto& d : g_pInputManager->m_vTabletTools) {
|
||||
for (auto const& d : g_pInputManager->m_vTabletTools) {
|
||||
result += std::format("\tTablet Tool at {:x}\n", (uintptr_t)d.get());
|
||||
}
|
||||
|
||||
result += "\n\nTouch:\n";
|
||||
|
||||
for (auto& d : g_pInputManager->m_vTouches) {
|
||||
for (auto const& d : g_pInputManager->m_vTouches) {
|
||||
result += std::format("\tTouch Device at {:x}:\n\t\t{}\n", (uintptr_t)d.get(), d->hlName);
|
||||
}
|
||||
|
||||
result += "\n\nSwitches:\n";
|
||||
|
||||
for (auto& d : g_pInputManager->m_lSwitches) {
|
||||
for (auto const& d : g_pInputManager->m_lSwitches) {
|
||||
result += std::format("\tSwitch Device at {:x}:\n\t\t{}\n", (uintptr_t)&d, d.pDevice ? d.pDevice->getName() : "");
|
||||
}
|
||||
}
|
||||
|
@ -712,21 +708,21 @@ std::string animationsRequest(eHyprCtlOutputFormat format, std::string request)
|
|||
if (format == eHyprCtlOutputFormat::FORMAT_NORMAL) {
|
||||
ret += "animations:\n";
|
||||
|
||||
for (auto& ac : g_pConfigManager->getAnimationConfig()) {
|
||||
for (auto const& ac : g_pConfigManager->getAnimationConfig()) {
|
||||
ret += std::format("\n\tname: {}\n\t\toverriden: {}\n\t\tbezier: {}\n\t\tenabled: {}\n\t\tspeed: {:.2f}\n\t\tstyle: {}\n", ac.first, (int)ac.second.overridden,
|
||||
ac.second.internalBezier, ac.second.internalEnabled, ac.second.internalSpeed, ac.second.internalStyle);
|
||||
}
|
||||
|
||||
ret += "beziers:\n";
|
||||
|
||||
for (auto& bz : g_pAnimationManager->getAllBeziers()) {
|
||||
for (auto const& bz : g_pAnimationManager->getAllBeziers()) {
|
||||
ret += std::format("\n\tname: {}\n", bz.first);
|
||||
}
|
||||
} else {
|
||||
// json
|
||||
|
||||
ret += "[[";
|
||||
for (auto& ac : g_pConfigManager->getAnimationConfig()) {
|
||||
for (auto const& ac : g_pConfigManager->getAnimationConfig()) {
|
||||
ret += std::format(R"#(
|
||||
{{
|
||||
"name": "{}",
|
||||
|
@ -744,7 +740,7 @@ std::string animationsRequest(eHyprCtlOutputFormat format, std::string request)
|
|||
|
||||
ret += ",\n[";
|
||||
|
||||
for (auto& bz : g_pAnimationManager->getAllBeziers()) {
|
||||
for (auto const& bz : g_pAnimationManager->getAllBeziers()) {
|
||||
ret += std::format(R"#(
|
||||
{{
|
||||
"name": "{}"
|
||||
|
@ -778,11 +774,11 @@ std::string globalShortcutsRequest(eHyprCtlOutputFormat format, std::string requ
|
|||
std::string ret = "";
|
||||
const auto SHORTCUTS = PROTO::globalShortcuts->getAllShortcuts();
|
||||
if (format == eHyprCtlOutputFormat::FORMAT_NORMAL) {
|
||||
for (auto& sh : SHORTCUTS)
|
||||
for (auto const& sh : SHORTCUTS)
|
||||
ret += std::format("{}:{} -> {}\n", sh.appid, sh.id, sh.description);
|
||||
} else {
|
||||
ret += "[";
|
||||
for (auto& sh : SHORTCUTS) {
|
||||
for (auto const& sh : SHORTCUTS) {
|
||||
ret += std::format(R"#(
|
||||
{{
|
||||
"name": "{}",
|
||||
|
@ -800,7 +796,7 @@ std::string globalShortcutsRequest(eHyprCtlOutputFormat format, std::string requ
|
|||
std::string bindsRequest(eHyprCtlOutputFormat format, std::string request) {
|
||||
std::string ret = "";
|
||||
if (format == eHyprCtlOutputFormat::FORMAT_NORMAL) {
|
||||
for (auto& kb : g_pKeybindManager->m_lKeybinds) {
|
||||
for (auto const& kb : g_pKeybindManager->m_lKeybinds) {
|
||||
ret += "bind";
|
||||
if (kb.locked)
|
||||
ret += "l";
|
||||
|
@ -821,7 +817,7 @@ std::string bindsRequest(eHyprCtlOutputFormat format, std::string request) {
|
|||
} else {
|
||||
// json
|
||||
ret += "[";
|
||||
for (auto& kb : g_pKeybindManager->m_lKeybinds) {
|
||||
for (auto const& kb : g_pKeybindManager->m_lKeybinds) {
|
||||
ret += std::format(
|
||||
R"#(
|
||||
{{
|
||||
|
@ -857,37 +853,47 @@ std::string versionRequest(eHyprCtlOutputFormat format, std::string request) {
|
|||
std::replace(commitMsg.begin(), commitMsg.end(), '#', ' ');
|
||||
|
||||
if (format == eHyprCtlOutputFormat::FORMAT_NORMAL) {
|
||||
std::string result = "Hyprland, built from branch " + std::string(GIT_BRANCH) + " at commit " + GIT_COMMIT_HASH + " " + GIT_DIRTY + " (" + commitMsg +
|
||||
").\nDate: " + GIT_COMMIT_DATE + "\nTag: " + GIT_TAG + ", commits: " + GIT_COMMITS + "\n\nflags: (if any)\n";
|
||||
std::string result = std::format("Hyprland {} built from branch {} at commit {} {} ({}).\n"
|
||||
"Date: {}\n"
|
||||
"Tag: {}, commits: {}\n"
|
||||
"built against aquamarine {}\n\n\n",
|
||||
HYPRLAND_VERSION, GIT_BRANCH, GIT_COMMIT_HASH, GIT_DIRTY, commitMsg, GIT_COMMIT_DATE, GIT_TAG, GIT_COMMITS, AQUAMARINE_VERSION);
|
||||
|
||||
#if (!defined(LEGACY_RENDERER) && !defined(ISDEBUG) && !defined(NO_XWAYLAND))
|
||||
result += "no flags were set\n";
|
||||
#else
|
||||
result += "flags set:\n";
|
||||
#ifdef LEGACY_RENDERER
|
||||
result += "legacyrenderer\n";
|
||||
#endif
|
||||
#ifndef ISDEBUG
|
||||
#ifdef ISDEBUG
|
||||
result += "debug\n";
|
||||
#endif
|
||||
#ifdef NO_XWAYLAND
|
||||
result += "no xwayland\n";
|
||||
#endif
|
||||
|
||||
#endif
|
||||
return result;
|
||||
} else {
|
||||
std::string result = std::format(
|
||||
R"#({{
|
||||
"branch": "{}",
|
||||
"commit": "{}",
|
||||
"version": "{}",
|
||||
"dirty": {},
|
||||
"commit_message": "{}",
|
||||
"commit_date": "{}",
|
||||
"tag": "{}",
|
||||
"commits": "{}",
|
||||
"buildAquamarine": "{}",
|
||||
"flags": [)#",
|
||||
GIT_BRANCH, GIT_COMMIT_HASH, (strcmp(GIT_DIRTY, "dirty") == 0 ? "true" : "false"), escapeJSONStrings(commitMsg), GIT_COMMIT_DATE, GIT_TAG, GIT_COMMITS);
|
||||
GIT_BRANCH, GIT_COMMIT_HASH, HYPRLAND_VERSION, (strcmp(GIT_DIRTY, "dirty") == 0 ? "true" : "false"), escapeJSONStrings(commitMsg), GIT_COMMIT_DATE, GIT_TAG,
|
||||
GIT_COMMITS, AQUAMARINE_VERSION);
|
||||
|
||||
#ifdef LEGACY_RENDERER
|
||||
result += "\"legacyrenderer\",";
|
||||
#endif
|
||||
#ifndef ISDEBUG
|
||||
#ifdef ISDEBUG
|
||||
result += "\"debug\",";
|
||||
#endif
|
||||
#ifdef NO_XWAYLAND
|
||||
|
@ -935,11 +941,14 @@ std::string systemInfoRequest(eHyprCtlOutputFormat format, std::string request)
|
|||
result += "os-release: " + execAndGet("cat /etc/os-release") + "\n\n";
|
||||
|
||||
result += "plugins:\n";
|
||||
for (auto& pl : g_pPluginSystem->getAllPlugins()) {
|
||||
if (g_pPluginSystem) {
|
||||
for (auto const& pl : g_pPluginSystem->getAllPlugins()) {
|
||||
result += std::format(" {} by {} ver {}\n", pl->name, pl->author, pl->version);
|
||||
}
|
||||
} else
|
||||
result += "\tunknown: not runtime\n";
|
||||
|
||||
if (g_pHyprCtl->m_sCurrentRequestParams.sysInfoConfig) {
|
||||
if (g_pHyprCtl && g_pHyprCtl->m_sCurrentRequestParams.sysInfoConfig) {
|
||||
result += "\n======Config-Start======\n";
|
||||
result += g_pConfigManager->getConfigString();
|
||||
result += "\n======Config-End========\n";
|
||||
|
@ -962,20 +971,34 @@ std::string dispatchRequest(eHyprCtlOutputFormat format, std::string in) {
|
|||
if (DISPATCHER == g_pKeybindManager->m_mDispatchers.end())
|
||||
return "Invalid dispatcher";
|
||||
|
||||
DISPATCHER->second(DISPATCHARG);
|
||||
SDispatchResult res = DISPATCHER->second(DISPATCHARG);
|
||||
|
||||
Debug::log(LOG, "Hyprctl: dispatcher {} : {}", DISPATCHSTR, DISPATCHARG);
|
||||
Debug::log(LOG, "Hyprctl: dispatcher {} : {}{}", DISPATCHSTR, DISPATCHARG, res.success ? "" : " -> " + res.error);
|
||||
|
||||
return "ok";
|
||||
return res.success ? "ok" : res.error;
|
||||
}
|
||||
|
||||
std::string dispatchKeyword(eHyprCtlOutputFormat format, std::string in) {
|
||||
// get rid of the keyword keyword
|
||||
in = in.substr(in.find_first_of(' ') + 1);
|
||||
// Find the first space to strip the keyword keyword
|
||||
auto const firstSpacePos = in.find_first_of(' ');
|
||||
if (firstSpacePos == std::string::npos) // Handle the case where there's no space found (invalid input)
|
||||
return "Invalid input: no space found";
|
||||
|
||||
const auto COMMAND = in.substr(0, in.find_first_of(' '));
|
||||
// Strip the keyword
|
||||
in = in.substr(firstSpacePos + 1);
|
||||
|
||||
const auto VALUE = in.substr(in.find_first_of(' ') + 1);
|
||||
// Find the next space for the COMMAND and VALUE
|
||||
auto const secondSpacePos = in.find_first_of(' ');
|
||||
if (secondSpacePos == std::string::npos) // Handle the case where there's no second space (invalid input)
|
||||
return "Invalid input: command and value not properly formatted";
|
||||
|
||||
// Extract COMMAND and VALUE
|
||||
const auto COMMAND = in.substr(0, secondSpacePos);
|
||||
const auto VALUE = in.substr(secondSpacePos + 1);
|
||||
|
||||
// If COMMAND is empty, handle accordingly
|
||||
if (COMMAND.empty())
|
||||
return "Invalid input: command is empty";
|
||||
|
||||
std::string retval = g_pConfigManager->parseKeyword(COMMAND, VALUE);
|
||||
|
||||
|
@ -1006,7 +1029,7 @@ std::string dispatchKeyword(eHyprCtlOutputFormat format, std::string in) {
|
|||
|
||||
// decorations will probably need a repaint
|
||||
if (COMMAND.contains("decoration:") || COMMAND.contains("border") || COMMAND == "workspace" || COMMAND.contains("zoom_factor") || COMMAND == "source") {
|
||||
for (auto& m : g_pCompositor->m_vMonitors) {
|
||||
for (auto const& m : g_pCompositor->m_vMonitors) {
|
||||
g_pHyprRenderer->damageMonitor(m.get());
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m->ID);
|
||||
}
|
||||
|
@ -1127,15 +1150,9 @@ std::string switchXKBLayoutRequest(eHyprCtlOutputFormat format, std::string requ
|
|||
const auto KB = vars[1];
|
||||
const auto CMD = vars[2];
|
||||
|
||||
// get kb
|
||||
const auto PKEYBOARD = std::find_if(g_pInputManager->m_vKeyboards.begin(), g_pInputManager->m_vKeyboards.end(),
|
||||
[&](const auto& other) { return other->hlName == g_pInputManager->deviceNameToInternalString(KB); });
|
||||
|
||||
if (PKEYBOARD == g_pInputManager->m_vKeyboards.end())
|
||||
return "device not found";
|
||||
|
||||
const auto KEEB = *PKEYBOARD;
|
||||
SP<IKeyboard> pKeyboard;
|
||||
|
||||
auto updateKeyboard = [](const SP<IKeyboard> KEEB, const std::string& CMD) -> std::optional<std::string> {
|
||||
const auto LAYOUTS = xkb_keymap_num_layouts(KEEB->xkbKeymap);
|
||||
xkb_layout_index_t activeLayout = 0;
|
||||
while (activeLayout < LAYOUTS) {
|
||||
|
@ -1162,6 +1179,43 @@ std::string switchXKBLayoutRequest(eHyprCtlOutputFormat format, std::string requ
|
|||
KEEB->updateModifiers(KEEB->modifiersState.depressed, KEEB->modifiersState.latched, KEEB->modifiersState.locked, requestedLayout);
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
};
|
||||
|
||||
if (KB == "main" || KB == "active" || KB == "current") {
|
||||
for (auto const& k : g_pInputManager->m_vKeyboards) {
|
||||
if (!k->active)
|
||||
continue;
|
||||
|
||||
pKeyboard = k;
|
||||
break;
|
||||
}
|
||||
} else if (KB == "all") {
|
||||
std::string result = "";
|
||||
for (auto const& k : g_pInputManager->m_vKeyboards) {
|
||||
auto res = updateKeyboard(k, CMD);
|
||||
if (res.has_value())
|
||||
result += *res + "\n";
|
||||
}
|
||||
return result.empty() ? "ok" : result;
|
||||
} else {
|
||||
auto k = std::find_if(g_pInputManager->m_vKeyboards.begin(), g_pInputManager->m_vKeyboards.end(),
|
||||
[&](const auto& other) { return other->hlName == g_pInputManager->deviceNameToInternalString(KB); });
|
||||
|
||||
if (k == g_pInputManager->m_vKeyboards.end())
|
||||
return "device not found";
|
||||
|
||||
pKeyboard = *k;
|
||||
}
|
||||
|
||||
if (!pKeyboard)
|
||||
return "no device";
|
||||
|
||||
auto result = updateKeyboard(pKeyboard, CMD);
|
||||
|
||||
if (result.has_value())
|
||||
return *result;
|
||||
|
||||
return "ok";
|
||||
}
|
||||
|
||||
|
@ -1286,7 +1340,7 @@ std::string dispatchSetProp(eHyprCtlOutputFormat format, std::string request) {
|
|||
g_pCompositor->focusWindow(PLASTWINDOW);
|
||||
}
|
||||
|
||||
for (auto& m : g_pCompositor->m_vMonitors)
|
||||
for (auto const& m : g_pCompositor->m_vMonitors)
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m->ID);
|
||||
|
||||
return "ok";
|
||||
|
@ -1359,7 +1413,7 @@ std::string decorationRequest(eHyprCtlOutputFormat format, std::string request)
|
|||
std::string result = "";
|
||||
if (format == eHyprCtlOutputFormat::FORMAT_JSON) {
|
||||
result += "[";
|
||||
for (auto& wd : PWINDOW->m_dWindowDecorations) {
|
||||
for (auto const& wd : PWINDOW->m_dWindowDecorations) {
|
||||
result += "{\n\"decorationName\": \"" + wd->getDisplayName() + "\",\n\"priority\": " + std::to_string(wd->getPositioningInfo().priority) + "\n},";
|
||||
}
|
||||
|
||||
|
@ -1367,7 +1421,7 @@ std::string decorationRequest(eHyprCtlOutputFormat format, std::string request)
|
|||
result += "]";
|
||||
} else {
|
||||
result = +"Decoration\tPriority\n";
|
||||
for (auto& wd : PWINDOW->m_dWindowDecorations) {
|
||||
for (auto const& wd : PWINDOW->m_dWindowDecorations) {
|
||||
result += wd->getDisplayName() + "\t" + std::to_string(wd->getPositioningInfo().priority) + "\n";
|
||||
}
|
||||
}
|
||||
|
@ -1386,7 +1440,7 @@ std::string dispatchOutput(eHyprCtlOutputFormat format, std::string request) {
|
|||
bool added = false;
|
||||
|
||||
if (!vars[3].empty()) {
|
||||
for (auto& m : g_pCompositor->m_vRealMonitors) {
|
||||
for (auto const& m : g_pCompositor->m_vRealMonitors) {
|
||||
if (m->szName == vars[3])
|
||||
return "Name already taken";
|
||||
}
|
||||
|
@ -1396,7 +1450,7 @@ std::string dispatchOutput(eHyprCtlOutputFormat format, std::string request) {
|
|||
if (g_pCompositor->getMonitorFromName(vars[3]))
|
||||
return "A real monitor already uses that name.";
|
||||
|
||||
for (auto& impl : g_pCompositor->m_pAqBackend->getImplementations() | std::views::reverse) {
|
||||
for (auto const& impl : g_pCompositor->m_pAqBackend->getImplementations() | std::views::reverse) {
|
||||
auto type = impl->type();
|
||||
|
||||
if (type == Aquamarine::AQ_BACKEND_HEADLESS && (vars[2] == "headless" || vars[2] == "auto")) {
|
||||
|
@ -1464,7 +1518,7 @@ std::string dispatchPlugin(eHyprCtlOutputFormat format, std::string request) {
|
|||
return "no plugins loaded";
|
||||
|
||||
std::string list = "";
|
||||
for (auto& p : PLUGINS) {
|
||||
for (auto const& p : PLUGINS) {
|
||||
list += std::format("\nPlugin {} by {}:\n\tHandle: {:x}\n\tVersion: {}\n\tDescription: {}\n", p->name, p->author, (uintptr_t)p->m_pHandle, p->version, p->description);
|
||||
}
|
||||
|
||||
|
@ -1561,6 +1615,29 @@ std::string getIsLocked(eHyprCtlOutputFormat format, std::string request) {
|
|||
return lockedStr;
|
||||
}
|
||||
|
||||
std::string getDescriptions(eHyprCtlOutputFormat format, std::string request) {
|
||||
std::string json = "{";
|
||||
const auto& DESCS = g_pConfigManager->getAllDescriptions();
|
||||
|
||||
for (const auto& d : DESCS) {
|
||||
json += d.jsonify() + ",\n";
|
||||
}
|
||||
|
||||
json.pop_back();
|
||||
json.pop_back();
|
||||
|
||||
json += "}\n";
|
||||
return json;
|
||||
}
|
||||
|
||||
std::string submapRequest(eHyprCtlOutputFormat format, std::string request) {
|
||||
std::string submap = g_pKeybindManager->getCurrentSubmap();
|
||||
if (submap.empty())
|
||||
submap = "default";
|
||||
|
||||
return format == FORMAT_JSON ? std::format("{{\"{}\"}}\n", escapeJSONStrings(submap)) : (submap + "\n");
|
||||
}
|
||||
|
||||
CHyprCtl::CHyprCtl() {
|
||||
registerCommand(SHyprCtlCommand{"workspaces", true, workspacesRequest});
|
||||
registerCommand(SHyprCtlCommand{"workspacerules", true, workspaceRulesRequest});
|
||||
|
@ -1581,6 +1658,8 @@ CHyprCtl::CHyprCtl() {
|
|||
registerCommand(SHyprCtlCommand{"layouts", true, layoutsRequest});
|
||||
registerCommand(SHyprCtlCommand{"configerrors", true, configErrorsRequest});
|
||||
registerCommand(SHyprCtlCommand{"locked", true, getIsLocked});
|
||||
registerCommand(SHyprCtlCommand{"descriptions", true, getDescriptions});
|
||||
registerCommand(SHyprCtlCommand{"submap", true, submapRequest});
|
||||
|
||||
registerCommand(SHyprCtlCommand{"monitors", false, monitorsRequest});
|
||||
registerCommand(SHyprCtlCommand{"reload", false, reloadRequest});
|
||||
|
@ -1657,7 +1736,7 @@ std::string CHyprCtl::getReply(std::string request) {
|
|||
std::string result = "";
|
||||
|
||||
// parse exact cmds first, then non-exact.
|
||||
for (auto& cmd : m_vCommands) {
|
||||
for (auto const& cmd : m_vCommands) {
|
||||
if (!cmd->exact)
|
||||
continue;
|
||||
|
||||
|
@ -1668,7 +1747,7 @@ std::string CHyprCtl::getReply(std::string request) {
|
|||
}
|
||||
|
||||
if (result.empty())
|
||||
for (auto& cmd : m_vCommands) {
|
||||
for (auto const& cmd : m_vCommands) {
|
||||
if (cmd->exact)
|
||||
continue;
|
||||
|
||||
|
@ -1699,7 +1778,7 @@ std::string CHyprCtl::getReply(std::string request) {
|
|||
rd.blurFBDirty = true;
|
||||
}
|
||||
|
||||
for (auto& m : g_pCompositor->m_vMonitors) {
|
||||
for (auto const& m : g_pCompositor->m_vMonitors) {
|
||||
g_pHyprRenderer->damageMonitor(m.get());
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m->ID);
|
||||
}
|
||||
|
|
|
@ -5,6 +5,10 @@
|
|||
#include "../helpers/MiscFunctions.hpp"
|
||||
#include <functional>
|
||||
|
||||
// exposed for main.cpp
|
||||
std::string systemInfoRequest(eHyprCtlOutputFormat format, std::string request);
|
||||
std::string versionRequest(eHyprCtlOutputFormat format, std::string request);
|
||||
|
||||
class CHyprCtl {
|
||||
public:
|
||||
CHyprCtl();
|
||||
|
|
|
@ -7,8 +7,8 @@ CHyprDebugOverlay::CHyprDebugOverlay() {
|
|||
m_pTexture = makeShared<CTexture>();
|
||||
}
|
||||
|
||||
void CHyprMonitorDebugOverlay::renderData(CMonitor* pMonitor, float µs) {
|
||||
m_dLastRenderTimes.push_back(µs / 1000.f);
|
||||
void CHyprMonitorDebugOverlay::renderData(CMonitor* pMonitor, float durationUs) {
|
||||
m_dLastRenderTimes.push_back(durationUs / 1000.f);
|
||||
|
||||
if (m_dLastRenderTimes.size() > (long unsigned int)pMonitor->refreshRate)
|
||||
m_dLastRenderTimes.pop_front();
|
||||
|
@ -17,8 +17,8 @@ void CHyprMonitorDebugOverlay::renderData(CMonitor* pMonitor, float µs) {
|
|||
m_pMonitor = pMonitor;
|
||||
}
|
||||
|
||||
void CHyprMonitorDebugOverlay::renderDataNoOverlay(CMonitor* pMonitor, float µs) {
|
||||
m_dLastRenderTimesNoOverlay.push_back(µs / 1000.f);
|
||||
void CHyprMonitorDebugOverlay::renderDataNoOverlay(CMonitor* pMonitor, float durationUs) {
|
||||
m_dLastRenderTimesNoOverlay.push_back(durationUs / 1000.f);
|
||||
|
||||
if (m_dLastRenderTimesNoOverlay.size() > (long unsigned int)pMonitor->refreshRate)
|
||||
m_dLastRenderTimesNoOverlay.pop_front();
|
||||
|
@ -57,7 +57,7 @@ int CHyprMonitorDebugOverlay::draw(int offset) {
|
|||
float avgFrametime = 0;
|
||||
float maxFrametime = 0;
|
||||
float minFrametime = 9999;
|
||||
for (auto& ft : m_dLastFrametimes) {
|
||||
for (auto const& ft : m_dLastFrametimes) {
|
||||
if (ft > maxFrametime)
|
||||
maxFrametime = ft;
|
||||
if (ft < minFrametime)
|
||||
|
@ -70,7 +70,7 @@ int CHyprMonitorDebugOverlay::draw(int offset) {
|
|||
float avgRenderTime = 0;
|
||||
float maxRenderTime = 0;
|
||||
float minRenderTime = 9999;
|
||||
for (auto& rt : m_dLastRenderTimes) {
|
||||
for (auto const& rt : m_dLastRenderTimes) {
|
||||
if (rt > maxRenderTime)
|
||||
maxRenderTime = rt;
|
||||
if (rt < minRenderTime)
|
||||
|
@ -83,7 +83,7 @@ int CHyprMonitorDebugOverlay::draw(int offset) {
|
|||
float avgRenderTimeNoOverlay = 0;
|
||||
float maxRenderTimeNoOverlay = 0;
|
||||
float minRenderTimeNoOverlay = 9999;
|
||||
for (auto& rt : m_dLastRenderTimesNoOverlay) {
|
||||
for (auto const& rt : m_dLastRenderTimesNoOverlay) {
|
||||
if (rt > maxRenderTimeNoOverlay)
|
||||
maxRenderTimeNoOverlay = rt;
|
||||
if (rt < minRenderTimeNoOverlay)
|
||||
|
@ -96,7 +96,7 @@ int CHyprMonitorDebugOverlay::draw(int offset) {
|
|||
float avgAnimMgrTick = 0;
|
||||
float maxAnimMgrTick = 0;
|
||||
float minAnimMgrTick = 9999;
|
||||
for (auto& at : m_dLastAnimationTicks) {
|
||||
for (auto const& at : m_dLastAnimationTicks) {
|
||||
if (at > maxAnimMgrTick)
|
||||
maxAnimMgrTick = at;
|
||||
if (at < minAnimMgrTick)
|
||||
|
@ -188,12 +188,12 @@ int CHyprMonitorDebugOverlay::draw(int offset) {
|
|||
return posY - offset;
|
||||
}
|
||||
|
||||
void CHyprDebugOverlay::renderData(CMonitor* pMonitor, float µs) {
|
||||
m_mMonitorOverlays[pMonitor].renderData(pMonitor, µs);
|
||||
void CHyprDebugOverlay::renderData(CMonitor* pMonitor, float durationUs) {
|
||||
m_mMonitorOverlays[pMonitor].renderData(pMonitor, durationUs);
|
||||
}
|
||||
|
||||
void CHyprDebugOverlay::renderDataNoOverlay(CMonitor* pMonitor, float µs) {
|
||||
m_mMonitorOverlays[pMonitor].renderDataNoOverlay(pMonitor, µs);
|
||||
void CHyprDebugOverlay::renderDataNoOverlay(CMonitor* pMonitor, float durationUs) {
|
||||
m_mMonitorOverlays[pMonitor].renderDataNoOverlay(pMonitor, durationUs);
|
||||
}
|
||||
|
||||
void CHyprDebugOverlay::frameData(CMonitor* pMonitor) {
|
||||
|
@ -217,7 +217,7 @@ void CHyprDebugOverlay::draw() {
|
|||
|
||||
// draw the things
|
||||
int offsetY = 0;
|
||||
for (auto& m : g_pCompositor->m_vMonitors) {
|
||||
for (auto const& m : g_pCompositor->m_vMonitors) {
|
||||
offsetY += m_mMonitorOverlays[m.get()].draw(offsetY);
|
||||
offsetY += 5; // for padding between mons
|
||||
}
|
||||
|
|
|
@ -13,8 +13,8 @@ class CHyprMonitorDebugOverlay {
|
|||
public:
|
||||
int draw(int offset);
|
||||
|
||||
void renderData(CMonitor* pMonitor, float µs);
|
||||
void renderDataNoOverlay(CMonitor* pMonitor, float µs);
|
||||
void renderData(CMonitor* pMonitor, float durationUs);
|
||||
void renderDataNoOverlay(CMonitor* pMonitor, float durationUs);
|
||||
void frameData(CMonitor* pMonitor);
|
||||
|
||||
private:
|
||||
|
@ -33,8 +33,8 @@ class CHyprDebugOverlay {
|
|||
public:
|
||||
CHyprDebugOverlay();
|
||||
void draw();
|
||||
void renderData(CMonitor*, float µs);
|
||||
void renderDataNoOverlay(CMonitor*, float µs);
|
||||
void renderData(CMonitor*, float durationUs);
|
||||
void renderDataNoOverlay(CMonitor*, float durationUs);
|
||||
void frameData(CMonitor*);
|
||||
|
||||
private:
|
||||
|
|
|
@ -37,14 +37,14 @@ CHyprNotificationOverlay::~CHyprNotificationOverlay() {
|
|||
void CHyprNotificationOverlay::addNotification(const std::string& text, const CColor& color, const float timeMs, const eIcons icon, const float fontSize) {
|
||||
const auto PNOTIF = m_dNotifications.emplace_back(std::make_unique<SNotification>()).get();
|
||||
|
||||
PNOTIF->text = text;
|
||||
PNOTIF->text = icon != eIcons::ICON_NONE ? " " + text /* tiny bit of padding otherwise icon touches text */ : text;
|
||||
PNOTIF->color = color == CColor(0) ? ICONS_COLORS[icon] : color;
|
||||
PNOTIF->started.reset();
|
||||
PNOTIF->timeMs = timeMs;
|
||||
PNOTIF->icon = icon;
|
||||
PNOTIF->fontSize = fontSize;
|
||||
|
||||
for (auto& m : g_pCompositor->m_vMonitors) {
|
||||
for (auto const& m : g_pCompositor->m_vMonitors) {
|
||||
g_pCompositor->scheduleFrameForMonitor(m.get());
|
||||
}
|
||||
}
|
||||
|
@ -87,7 +87,7 @@ CBox CHyprNotificationOverlay::drawNotifications(CMonitor* pMonitor) {
|
|||
const auto iconBackendID = iconBackendFromLayout(layout);
|
||||
const auto PBEZIER = g_pAnimationManager->getBezier("default");
|
||||
|
||||
for (auto& notif : m_dNotifications) {
|
||||
for (auto const& notif : m_dNotifications) {
|
||||
const auto ICONPADFORNOTIF = notif->icon == ICON_NONE ? 0 : ICON_PAD;
|
||||
const auto FONTSIZE = std::clamp((int)(notif->fontSize * ((pMonitor->vecPixelSize.x * SCALE) / 1920.f)), 8, 40);
|
||||
|
||||
|
|
|
@ -4,11 +4,14 @@
|
|||
#include "RollingLogFollow.hpp"
|
||||
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <print>
|
||||
#include <fcntl.h>
|
||||
|
||||
void Debug::init(const std::string& IS) {
|
||||
logFile = IS + (ISDEBUG ? "/hyprlandd.log" : "/hyprland.log");
|
||||
logOfs.open(logFile, std::ios::out | std::ios::app);
|
||||
auto handle = logOfs.native_handle();
|
||||
fcntl(handle, F_SETFD, FD_CLOEXEC);
|
||||
}
|
||||
|
||||
void Debug::close() {
|
||||
|
@ -66,5 +69,5 @@ void Debug::log(LogLevel level, std::string str) {
|
|||
|
||||
// log it to the stdout too.
|
||||
if (!disableStdout)
|
||||
std::cout << ((coloredLogs && !**coloredLogs) ? str : coloredStr) << "\n";
|
||||
std::println("{}", ((coloredLogs && !**coloredLogs) ? str : coloredStr));
|
||||
}
|
||||
|
|
|
@ -55,7 +55,8 @@ namespace Debug {
|
|||
// print date and time to the ofs
|
||||
if (disableTime && !**disableTime) {
|
||||
#ifndef _LIBCPP_VERSION
|
||||
const auto zt = std::chrono::zoned_time{std::chrono::current_zone(), std::chrono::system_clock::now()};
|
||||
static auto current_zone = std::chrono::current_zone();
|
||||
const auto zt = std::chrono::zoned_time{current_zone, std::chrono::system_clock::now()};
|
||||
const auto hms = std::chrono::hh_mm_ss{zt.get_local_time() - std::chrono::floor<std::chrono::days>(zt.get_local_time())};
|
||||
#else
|
||||
// TODO: current clang 17 does not support `zoned_time`, remove this once clang 19 is ready
|
||||
|
@ -72,6 +73,5 @@ namespace Debug {
|
|||
logMsg += std::vformat(fmt.get(), std::make_format_args(args...));
|
||||
|
||||
log(level, logMsg);
|
||||
logMutex.unlock();
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
#include "includes.hpp"
|
||||
#include "debug/Log.hpp"
|
||||
#include "helpers/WLListener.hpp"
|
||||
#include "helpers/Color.hpp"
|
||||
#include "macros.hpp"
|
||||
#include "desktop/DesktopTypes.hpp"
|
||||
|
|
|
@ -71,6 +71,12 @@ CLayerSurface::~CLayerSurface() {
|
|||
surface->unassign();
|
||||
g_pHyprRenderer->makeEGLCurrent();
|
||||
std::erase_if(g_pHyprOpenGL->m_mLayerFramebuffers, [&](const auto& other) { return other.first.expired() || other.first.lock() == self.lock(); });
|
||||
|
||||
for (auto const& mon : g_pCompositor->m_vRealMonitors) {
|
||||
for (auto& lsl : mon->m_aLayerSurfaceLayers) {
|
||||
std::erase_if(lsl, [this](auto& ls) { return ls.expired() || ls.get() == this; });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CLayerSurface::onDestroy() {
|
||||
|
@ -360,7 +366,7 @@ void CLayerSurface::applyRules() {
|
|||
xray = -1;
|
||||
animationStyle.reset();
|
||||
|
||||
for (auto& rule : g_pConfigManager->getMatchingRules(self.lock())) {
|
||||
for (auto const& rule : g_pConfigManager->getMatchingRules(self.lock())) {
|
||||
if (rule.rule == "noanim")
|
||||
noAnimations = true;
|
||||
else if (rule.rule == "blur")
|
||||
|
@ -388,6 +394,11 @@ void CLayerSurface::applyRules() {
|
|||
} else if (rule.rule.starts_with("animation")) {
|
||||
CVarList vars{rule.rule, 2, 's'};
|
||||
animationStyle = vars[1];
|
||||
} else if (rule.rule.starts_with("order")) {
|
||||
CVarList vars{rule.rule, 2, 's'};
|
||||
try {
|
||||
order = std::stoi(vars[1]);
|
||||
} catch (...) { Debug::log(ERR, "Invalid value passed to order"); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@ class CLayerSurface {
|
|||
bool mapped = false;
|
||||
uint32_t layer = 0;
|
||||
|
||||
int monitorID = -1;
|
||||
MONITORID monitorID = -1;
|
||||
|
||||
bool fadingOut = false;
|
||||
bool readyToDelete = false;
|
||||
|
@ -51,10 +51,11 @@ class CLayerSurface {
|
|||
|
||||
bool forceBlur = false;
|
||||
bool forceBlurPopups = false;
|
||||
int xray = -1;
|
||||
int64_t xray = -1;
|
||||
bool ignoreAlpha = false;
|
||||
float ignoreAlphaValue = 0.f;
|
||||
bool dimAround = false;
|
||||
int64_t order = 0;
|
||||
|
||||
std::optional<std::string> animationStyle;
|
||||
|
||||
|
|
|
@ -202,6 +202,13 @@ void CPopup::reposition() {
|
|||
m_pResource->applyPositioning(box, COORDS);
|
||||
}
|
||||
|
||||
SP<CWLSurface> CPopup::getT1Owner() {
|
||||
if (m_pWindowOwner)
|
||||
return m_pWindowOwner->m_pWLSurface;
|
||||
else
|
||||
return m_pLayerOwner->surface;
|
||||
}
|
||||
|
||||
Vector2D CPopup::coordsRelativeToParent() {
|
||||
Vector2D offset;
|
||||
|
||||
|
@ -251,7 +258,7 @@ void CPopup::recheckTree() {
|
|||
|
||||
void CPopup::recheckChildrenRecursive() {
|
||||
auto cpy = m_vChildren;
|
||||
for (auto& c : cpy) {
|
||||
for (auto const& c : cpy) {
|
||||
c->onCommit(true);
|
||||
c->recheckChildrenRecursive();
|
||||
}
|
||||
|
@ -282,14 +289,14 @@ bool CPopup::visible() {
|
|||
}
|
||||
|
||||
void CPopup::bfHelper(std::vector<CPopup*> nodes, std::function<void(CPopup*, void*)> fn, void* data) {
|
||||
for (auto& n : nodes) {
|
||||
for (auto const& n : nodes) {
|
||||
fn(n, data);
|
||||
}
|
||||
|
||||
std::vector<CPopup*> nodes2;
|
||||
|
||||
for (auto& n : nodes) {
|
||||
for (auto& c : n->m_vChildren) {
|
||||
for (auto const& n : nodes) {
|
||||
for (auto const& c : n->m_vChildren) {
|
||||
nodes2.push_back(c.get());
|
||||
}
|
||||
}
|
||||
|
@ -308,7 +315,7 @@ CPopup* CPopup::at(const Vector2D& globalCoords, bool allowsInput) {
|
|||
std::vector<CPopup*> popups;
|
||||
breadthfirst([](CPopup* popup, void* data) { ((std::vector<CPopup*>*)data)->push_back(popup); }, &popups);
|
||||
|
||||
for (auto& p : popups | std::views::reverse) {
|
||||
for (auto const& p : popups | std::views::reverse) {
|
||||
if (!p->m_pResource)
|
||||
continue;
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@ class CPopup {
|
|||
|
||||
~CPopup();
|
||||
|
||||
SP<CWLSurface> getT1Owner();
|
||||
Vector2D coordsRelativeToParent();
|
||||
Vector2D coordsGlobal();
|
||||
|
||||
|
|
|
@ -30,13 +30,7 @@ CSubsurface::CSubsurface(SP<CWLSubsurfaceResource> pSubsurface, CPopup* pOwner)
|
|||
}
|
||||
|
||||
CSubsurface::~CSubsurface() {
|
||||
hyprListener_newSubsurface.removeCallback();
|
||||
|
||||
if (!m_pSubsurface)
|
||||
return;
|
||||
|
||||
hyprListener_commitSubsurface.removeCallback();
|
||||
hyprListener_destroySubsurface.removeCallback();
|
||||
;
|
||||
}
|
||||
|
||||
void CSubsurface::initSignals() {
|
||||
|
@ -65,7 +59,7 @@ void CSubsurface::checkSiblingDamage() {
|
|||
|
||||
const double SCALE = m_pWindowParent.lock() && m_pWindowParent->m_bIsX11 ? 1.0 / m_pWindowParent->m_fX11SurfaceScaledBy : 1.0;
|
||||
|
||||
for (auto& n : m_pParent->m_vChildren) {
|
||||
for (auto const& n : m_pParent->m_vChildren) {
|
||||
if (n.get() == this)
|
||||
continue;
|
||||
|
||||
|
@ -75,7 +69,7 @@ void CSubsurface::checkSiblingDamage() {
|
|||
}
|
||||
|
||||
void CSubsurface::recheckDamageForSubsurfaces() {
|
||||
for (auto& n : m_vChildren) {
|
||||
for (auto const& n : m_vChildren) {
|
||||
const auto COORDS = n->coordsGlobal();
|
||||
g_pHyprRenderer->damageSurface(n->m_pWLSurface->resource(), COORDS.x, COORDS.y);
|
||||
}
|
||||
|
@ -183,7 +177,7 @@ Vector2D CSubsurface::coordsGlobal() {
|
|||
}
|
||||
|
||||
void CSubsurface::initExistingSubsurfaces(SP<CWLSurfaceResource> pSurface) {
|
||||
for (auto& s : pSurface->subsurfaces) {
|
||||
for (auto const& s : pSurface->subsurfaces) {
|
||||
if (!s || s->surface->hlSurface /* already assigned */)
|
||||
continue;
|
||||
onNewSubsurface(s.lock());
|
||||
|
|
|
@ -35,10 +35,6 @@ class CSubsurface {
|
|||
void recheckDamageForSubsurfaces();
|
||||
|
||||
private:
|
||||
DYNLISTENER(destroySubsurface);
|
||||
DYNLISTENER(commitSubsurface);
|
||||
DYNLISTENER(newSubsurface);
|
||||
|
||||
struct {
|
||||
CHyprSignalListener destroySubsurface;
|
||||
CHyprSignalListener commitSubsurface;
|
||||
|
|
|
@ -62,7 +62,7 @@ bool CWLSurface::small() const {
|
|||
|
||||
const auto O = m_pWindowOwner.lock();
|
||||
|
||||
return O->m_vReportedSize.x > m_pResource->current.bufferSize.x + 1 || O->m_vReportedSize.y > m_pResource->current.bufferSize.y + 1;
|
||||
return O->m_vReportedSize.x > m_pResource->current.size.x + 1 || O->m_vReportedSize.y > m_pResource->current.size.y + 1;
|
||||
}
|
||||
|
||||
Vector2D CWLSurface::correctSmallVec() const {
|
||||
|
|
|
@ -21,7 +21,6 @@ PHLWINDOW CWindow::create(SP<CXWaylandSurface> surface) {
|
|||
|
||||
pWindow->m_pSelf = pWindow;
|
||||
pWindow->m_bIsX11 = true;
|
||||
pWindow->m_iX11Type = surface->overrideRedirect ? 2 : 1;
|
||||
|
||||
pWindow->m_vRealPosition.create(g_pConfigManager->getAnimationPropertyConfig("windowsIn"), pWindow, AVARDAMAGE_ENTIRE);
|
||||
pWindow->m_vRealSize.create(g_pConfigManager->getAnimationPropertyConfig("windowsIn"), pWindow, AVARDAMAGE_ENTIRE);
|
||||
|
@ -31,6 +30,7 @@ PHLWINDOW CWindow::create(SP<CXWaylandSurface> surface) {
|
|||
pWindow->m_fActiveInactiveAlpha.create(g_pConfigManager->getAnimationPropertyConfig("fadeSwitch"), pWindow, AVARDAMAGE_ENTIRE);
|
||||
pWindow->m_cRealShadowColor.create(g_pConfigManager->getAnimationPropertyConfig("fadeShadow"), pWindow, AVARDAMAGE_SHADOW);
|
||||
pWindow->m_fDimPercent.create(g_pConfigManager->getAnimationPropertyConfig("fadeDim"), pWindow, AVARDAMAGE_ENTIRE);
|
||||
pWindow->m_fMovingToWorkspaceAlpha.create(g_pConfigManager->getAnimationPropertyConfig("fadeOut"), pWindow, AVARDAMAGE_ENTIRE);
|
||||
|
||||
pWindow->addWindowDeco(std::make_unique<CHyprDropShadowDecoration>(pWindow));
|
||||
pWindow->addWindowDeco(std::make_unique<CHyprBorderDecoration>(pWindow));
|
||||
|
@ -52,6 +52,7 @@ PHLWINDOW CWindow::create(SP<CXDGSurfaceResource> resource) {
|
|||
pWindow->m_fActiveInactiveAlpha.create(g_pConfigManager->getAnimationPropertyConfig("fadeSwitch"), pWindow, AVARDAMAGE_ENTIRE);
|
||||
pWindow->m_cRealShadowColor.create(g_pConfigManager->getAnimationPropertyConfig("fadeShadow"), pWindow, AVARDAMAGE_SHADOW);
|
||||
pWindow->m_fDimPercent.create(g_pConfigManager->getAnimationPropertyConfig("fadeDim"), pWindow, AVARDAMAGE_ENTIRE);
|
||||
pWindow->m_fMovingToWorkspaceAlpha.create(g_pConfigManager->getAnimationPropertyConfig("fadeOut"), pWindow, AVARDAMAGE_ENTIRE);
|
||||
|
||||
pWindow->addWindowDeco(std::make_unique<CHyprDropShadowDecoration>(pWindow));
|
||||
pWindow->addWindowDeco(std::make_unique<CHyprBorderDecoration>(pWindow));
|
||||
|
@ -252,7 +253,7 @@ void CWindow::updateWindowDecos() {
|
|||
if (!m_bIsMapped || isHidden())
|
||||
return;
|
||||
|
||||
for (auto& wd : m_vDecosToRemove) {
|
||||
for (auto const& wd : m_vDecosToRemove) {
|
||||
for (auto it = m_dWindowDecorations.begin(); it != m_dWindowDecorations.end(); it++) {
|
||||
if (it->get() == wd) {
|
||||
g_pDecorationPositioner->uncacheDecoration(it->get());
|
||||
|
@ -270,11 +271,11 @@ void CWindow::updateWindowDecos() {
|
|||
// make a copy because updateWindow can remove decos.
|
||||
std::vector<IHyprWindowDecoration*> decos;
|
||||
|
||||
for (auto& wd : m_dWindowDecorations) {
|
||||
for (auto const& wd : m_dWindowDecorations) {
|
||||
decos.push_back(wd.get());
|
||||
}
|
||||
|
||||
for (auto& wd : decos) {
|
||||
for (auto const& wd : decos) {
|
||||
if (std::find_if(m_dWindowDecorations.begin(), m_dWindowDecorations.end(), [wd](const auto& other) { return other.get() == wd; }) == m_dWindowDecorations.end())
|
||||
continue;
|
||||
wd->updateWindow(m_pSelf.lock());
|
||||
|
@ -296,7 +297,7 @@ void CWindow::removeWindowDeco(IHyprWindowDecoration* deco) {
|
|||
}
|
||||
|
||||
void CWindow::uncacheWindowDecos() {
|
||||
for (auto& wd : m_dWindowDecorations) {
|
||||
for (auto const& wd : m_dWindowDecorations) {
|
||||
g_pDecorationPositioner->uncacheDecoration(wd.get());
|
||||
}
|
||||
}
|
||||
|
@ -305,7 +306,7 @@ bool CWindow::checkInputOnDecos(const eInputType type, const Vector2D& mouseCoor
|
|||
if (type != INPUT_TYPE_DRAG_END && hasPopupAt(mouseCoords))
|
||||
return false;
|
||||
|
||||
for (auto& wd : m_dWindowDecorations) {
|
||||
for (auto const& wd : m_dWindowDecorations) {
|
||||
if (!(wd->getDecorationFlags() & DECORATION_ALLOWS_MOUSE_INPUT))
|
||||
continue;
|
||||
|
||||
|
@ -337,7 +338,7 @@ pid_t CWindow::getPID() {
|
|||
}
|
||||
|
||||
IHyprWindowDecoration* CWindow::getDecorationByType(eDecorationType type) {
|
||||
for (auto& wd : m_dWindowDecorations) {
|
||||
for (auto const& wd : m_dWindowDecorations) {
|
||||
if (wd->getDecorationType() == type)
|
||||
return wd.get();
|
||||
}
|
||||
|
@ -407,6 +408,11 @@ void CWindow::moveToWorkspace(PHLWORKSPACE pWorkspace) {
|
|||
|
||||
const auto OLDWORKSPACE = m_pWorkspace;
|
||||
|
||||
m_iMonitorMovedFrom = OLDWORKSPACE ? OLDWORKSPACE->m_iMonitorID : -1;
|
||||
m_fMovingToWorkspaceAlpha.setValueAndWarp(1.F);
|
||||
m_fMovingToWorkspaceAlpha = 0.F;
|
||||
m_fMovingToWorkspaceAlpha.setCallbackOnEnd([this](void* thisptr) { m_iMonitorMovedFrom = -1; });
|
||||
|
||||
m_pWorkspace = pWorkspace;
|
||||
|
||||
setAnimationsToMove();
|
||||
|
@ -446,15 +452,21 @@ PHLWINDOW CWindow::X11TransientFor() {
|
|||
return nullptr;
|
||||
|
||||
auto s = m_pXWaylandSurface->parent;
|
||||
auto oldParent = s;
|
||||
std::vector<SP<CXWaylandSurface>> visited;
|
||||
while (s) {
|
||||
// break cyclic loop of m_pXWaylandSurface being parent of itself, #TODO reject this from even being created?
|
||||
if (!s->parent || s->parent == oldParent)
|
||||
// break loops. Some X apps make them, and it seems like it's valid behavior?!?!?!
|
||||
// TODO: we should reject loops being created in the first place.
|
||||
if (std::find(visited.begin(), visited.end(), s) != visited.end())
|
||||
break;
|
||||
|
||||
visited.emplace_back(s.lock());
|
||||
s = s->parent;
|
||||
}
|
||||
|
||||
for (auto& w : g_pCompositor->m_vWindows) {
|
||||
if (s == m_pXWaylandSurface)
|
||||
return nullptr; // dead-ass circle
|
||||
|
||||
for (auto const& w : g_pCompositor->m_vWindows) {
|
||||
if (w->m_pXWaylandSurface != s)
|
||||
continue;
|
||||
return w;
|
||||
|
@ -464,7 +476,7 @@ PHLWINDOW CWindow::X11TransientFor() {
|
|||
}
|
||||
|
||||
void CWindow::removeDecorationByType(eDecorationType type) {
|
||||
for (auto& wd : m_dWindowDecorations) {
|
||||
for (auto const& wd : m_dWindowDecorations) {
|
||||
if (wd->getDecorationType() == type)
|
||||
m_vDecosToRemove.push_back(wd.get());
|
||||
}
|
||||
|
@ -502,6 +514,7 @@ void CWindow::onUnmap() {
|
|||
m_fAlpha.setCallbackOnEnd(unregisterVar);
|
||||
m_cRealShadowColor.setCallbackOnEnd(unregisterVar);
|
||||
m_fDimPercent.setCallbackOnEnd(unregisterVar);
|
||||
m_fMovingToWorkspaceAlpha.setCallbackOnEnd(unregisterVar);
|
||||
|
||||
m_vRealSize.setCallbackOnBegin(nullptr);
|
||||
|
||||
|
@ -542,6 +555,7 @@ void CWindow::onMap() {
|
|||
m_fAlpha.resetAllCallbacks();
|
||||
m_cRealShadowColor.resetAllCallbacks();
|
||||
m_fDimPercent.resetAllCallbacks();
|
||||
m_fMovingToWorkspaceAlpha.resetAllCallbacks();
|
||||
|
||||
m_vRealPosition.registerVar();
|
||||
m_vRealSize.registerVar();
|
||||
|
@ -551,6 +565,7 @@ void CWindow::onMap() {
|
|||
m_fAlpha.registerVar();
|
||||
m_cRealShadowColor.registerVar();
|
||||
m_fDimPercent.registerVar();
|
||||
m_fMovingToWorkspaceAlpha.registerVar();
|
||||
|
||||
m_fBorderAngleAnimationProgress.setCallbackOnEnd([&](void* ptr) { onBorderAngleAnimEnd(ptr); }, false);
|
||||
|
||||
|
@ -617,7 +632,7 @@ void CWindow::applyDynamicRule(const SWindowRule& r) {
|
|||
|
||||
int opacityIDX = 0;
|
||||
|
||||
for (auto& r : vars) {
|
||||
for (auto const& r : vars) {
|
||||
if (r == "opacity")
|
||||
continue;
|
||||
|
||||
|
@ -666,7 +681,7 @@ void CWindow::applyDynamicRule(const SWindowRule& r) {
|
|||
return;
|
||||
}
|
||||
|
||||
for (auto& token : colorsAndAngles) {
|
||||
for (auto const& token : colorsAndAngles) {
|
||||
// The first angle, or an explicit "0deg", splits the two gradients
|
||||
if (active && token.contains("deg")) {
|
||||
activeBorderGradient.m_fAngle = std::stoi(token.substr(0, token.size() - 3)) * (PI / 180.0);
|
||||
|
@ -727,9 +742,8 @@ void CWindow::applyDynamicRule(const SWindowRule& r) {
|
|||
}
|
||||
|
||||
m_sWindowData.maxSize = CWindowOverridableVar(VEC, priority);
|
||||
m_vRealSize =
|
||||
Vector2D(std::min((double)m_sWindowData.maxSize.value().x, m_vRealSize.goal().x), std::min((double)m_sWindowData.maxSize.value().y, m_vRealSize.goal().y));
|
||||
g_pXWaylandManager->setWindowSize(m_pSelf.lock(), m_vRealSize.goal());
|
||||
clampWindowSize(std::nullopt, m_sWindowData.maxSize.value());
|
||||
|
||||
} catch (std::exception& e) { Debug::log(ERR, "maxsize rule \"{}\" failed with: {}", r.szRule, e.what()); }
|
||||
} else if (r.szRule.starts_with("minsize")) {
|
||||
try {
|
||||
|
@ -742,12 +756,14 @@ void CWindow::applyDynamicRule(const SWindowRule& r) {
|
|||
}
|
||||
|
||||
m_sWindowData.minSize = CWindowOverridableVar(VEC, priority);
|
||||
m_vRealSize =
|
||||
Vector2D(std::max((double)m_sWindowData.minSize.value().x, m_vRealSize.goal().x), std::max((double)m_sWindowData.minSize.value().y, m_vRealSize.goal().y));
|
||||
g_pXWaylandManager->setWindowSize(m_pSelf.lock(), m_vRealSize.goal());
|
||||
clampWindowSize(m_sWindowData.minSize.value(), std::nullopt);
|
||||
|
||||
if (m_sGroupData.pNextWindow.expired())
|
||||
setHidden(false);
|
||||
} catch (std::exception& e) { Debug::log(ERR, "minsize rule \"{}\" failed with: {}", r.szRule, e.what()); }
|
||||
} else if (r.szRule == "renderunfocused") {
|
||||
m_sWindowData.renderUnfocused = CWindowOverridableVar(true, priority);
|
||||
g_pHyprRenderer->addWindowToRenderUnfocused(m_pSelf.lock());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -765,12 +781,14 @@ void CWindow::updateDynamicRules() {
|
|||
m_sWindowData.activeBorderColor.unset(PRIORITY_WINDOW_RULE);
|
||||
m_sWindowData.inactiveBorderColor.unset(PRIORITY_WINDOW_RULE);
|
||||
|
||||
m_sWindowData.renderUnfocused.unset(PRIORITY_WINDOW_RULE);
|
||||
|
||||
m_eIdleInhibitMode = IDLEINHIBIT_NONE;
|
||||
|
||||
m_tags.removeDynamicTags();
|
||||
|
||||
m_vMatchedRules = g_pConfigManager->getMatchingRules(m_pSelf.lock());
|
||||
for (auto& r : m_vMatchedRules) {
|
||||
for (auto const& r : m_vMatchedRules) {
|
||||
applyDynamicRule(r);
|
||||
}
|
||||
|
||||
|
@ -881,7 +899,7 @@ void CWindow::destroyGroup() {
|
|||
addresses += std::format("{:x},", (uintptr_t)curr.get());
|
||||
} while (curr.get() != this);
|
||||
|
||||
for (auto& w : members) {
|
||||
for (auto const& w : members) {
|
||||
if (w->m_sGroupData.head)
|
||||
g_pLayoutManager->getCurrentLayout()->onWindowRemoved(curr);
|
||||
w->m_sGroupData.head = false;
|
||||
|
@ -889,7 +907,7 @@ void CWindow::destroyGroup() {
|
|||
|
||||
const bool GROUPSLOCKEDPREV = g_pKeybindManager->m_bGroupsLocked;
|
||||
g_pKeybindManager->m_bGroupsLocked = true;
|
||||
for (auto& w : members) {
|
||||
for (auto const& w : members) {
|
||||
g_pLayoutManager->getCurrentLayout()->onWindowCreated(w);
|
||||
w->updateWindowDecos();
|
||||
}
|
||||
|
@ -937,12 +955,16 @@ int CWindow::getGroupSize() {
|
|||
}
|
||||
|
||||
bool CWindow::canBeGroupedInto(PHLWINDOW pWindow) {
|
||||
static auto ALLOWGROUPMERGE = CConfigValue<Hyprlang::INT>("group:merge_groups_on_drag");
|
||||
bool isGroup = m_sGroupData.pNextWindow;
|
||||
bool disallowDragIntoGroup = g_pInputManager->m_bWasDraggingWindow && isGroup && !bool(*ALLOWGROUPMERGE);
|
||||
return !g_pKeybindManager->m_bGroupsLocked // global group lock disengaged
|
||||
&& ((m_eGroupRules & GROUP_INVADE && m_bFirstMap) // window ignore local group locks, or
|
||||
|| (!pWindow->getGroupHead()->m_sGroupData.locked // target unlocked
|
||||
&& !(m_sGroupData.pNextWindow.lock() && getGroupHead()->m_sGroupData.locked))) // source unlocked or isn't group
|
||||
&& !m_sGroupData.deny // source is not denied entry
|
||||
&& !(m_eGroupRules & GROUP_BARRED && m_bFirstMap); // group rule doesn't prevent adding window
|
||||
&& !(m_eGroupRules & GROUP_BARRED && m_bFirstMap) // group rule doesn't prevent adding window
|
||||
&& !disallowDragIntoGroup; // config allows groups to be merged
|
||||
}
|
||||
|
||||
PHLWINDOW CWindow::getGroupWindowByIndex(int index) {
|
||||
|
@ -973,7 +995,7 @@ void CWindow::setGroupCurrent(PHLWINDOW pWindow) {
|
|||
const auto PCURRENT = getGroupCurrent();
|
||||
const bool FULLSCREEN = PCURRENT->isFullscreen();
|
||||
const auto WORKSPACE = PCURRENT->m_pWorkspace;
|
||||
const auto MODE = PCURRENT->m_sFullscreenState.client;
|
||||
const auto MODE = PCURRENT->m_sFullscreenState.internal;
|
||||
|
||||
const auto PWINDOWSIZE = PCURRENT->m_vRealSize.goal();
|
||||
const auto PWINDOWPOS = PCURRENT->m_vRealPosition.goal();
|
||||
|
@ -1235,6 +1257,16 @@ int CWindow::surfacesCount() {
|
|||
return no;
|
||||
}
|
||||
|
||||
void CWindow::clampWindowSize(const std::optional<Vector2D> minSize, const std::optional<Vector2D> maxSize) {
|
||||
const Vector2D REALSIZE = m_vRealSize.goal();
|
||||
const Vector2D NEWSIZE = REALSIZE.clamp(minSize.value_or(Vector2D{0.f, 0.f}), maxSize.value_or(Vector2D{INFINITY, INFINITY}));
|
||||
const Vector2D DELTA = REALSIZE - NEWSIZE;
|
||||
|
||||
m_vRealPosition = m_vRealPosition.goal() + DELTA / 2.0;
|
||||
m_vRealSize = NEWSIZE;
|
||||
g_pXWaylandManager->setWindowSize(m_pSelf.lock(), NEWSIZE);
|
||||
}
|
||||
|
||||
bool CWindow::isFullscreen() {
|
||||
return m_sFullscreenState.internal != FSMODE_NONE;
|
||||
}
|
||||
|
@ -1243,7 +1275,7 @@ bool CWindow::isEffectiveInternalFSMode(const eFullscreenMode MODE) {
|
|||
return (eFullscreenMode)std::bit_floor((uint8_t)m_sFullscreenState.internal) == MODE;
|
||||
}
|
||||
|
||||
int CWindow::workspaceID() {
|
||||
WORKSPACEID CWindow::workspaceID() {
|
||||
return m_pWorkspace ? m_pWorkspace->m_iID : m_iLastWorkspace;
|
||||
}
|
||||
|
||||
|
@ -1282,7 +1314,7 @@ std::unordered_map<std::string, std::string> CWindow::getEnv() {
|
|||
|
||||
CVarList envs(std::string{buffer.data(), buffer.size() - 1}, 0, '\n', true);
|
||||
|
||||
for (auto& e : envs) {
|
||||
for (auto const& e : envs) {
|
||||
if (!e.contains('='))
|
||||
continue;
|
||||
|
||||
|
@ -1307,6 +1339,11 @@ void CWindow::activate(bool force) {
|
|||
if (!force && (!m_sWindowData.focusOnActivate.valueOr(*PFOCUSONACTIVATE) || (m_eSuppressedEvents & SUPPRESS_ACTIVATE_FOCUSONLY) || (m_eSuppressedEvents & SUPPRESS_ACTIVATE)))
|
||||
return;
|
||||
|
||||
if (!m_bIsMapped) {
|
||||
Debug::log(LOG, "Ignoring CWindow::activate focus/warp, window is not mapped yet.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_bIsFloating)
|
||||
g_pCompositor->changeWindowZOrder(m_pSelf.lock(), true);
|
||||
|
||||
|
@ -1511,7 +1548,7 @@ PHLWINDOW CWindow::getSwallower() {
|
|||
if (!currentPid)
|
||||
break;
|
||||
|
||||
for (auto& w : g_pCompositor->m_vWindows) {
|
||||
for (auto const& w : g_pCompositor->m_vWindows) {
|
||||
if (!w->m_bIsMapped || w->isHidden())
|
||||
continue;
|
||||
|
||||
|
@ -1536,7 +1573,7 @@ PHLWINDOW CWindow::getSwallower() {
|
|||
return candidates.at(0);
|
||||
|
||||
// walk up the focus history and find the last focused
|
||||
for (auto& w : g_pCompositor->m_vWindowFocusHistory) {
|
||||
for (auto const& w : g_pCompositor->m_vWindowFocusHistory) {
|
||||
if (!w)
|
||||
continue;
|
||||
|
||||
|
@ -1556,3 +1593,11 @@ void CWindow::unsetWindowData(eOverridePriority priority) {
|
|||
element.second(m_pSelf.lock())->unset(priority);
|
||||
}
|
||||
}
|
||||
|
||||
bool CWindow::isX11OverrideRedirect() {
|
||||
return m_pXWaylandSurface && m_pXWaylandSurface->overrideRedirect;
|
||||
}
|
||||
|
||||
bool CWindow::isModal() {
|
||||
return (m_pXWaylandSurface && m_pXWaylandSurface->modal);
|
||||
}
|
||||
|
|
|
@ -174,6 +174,7 @@ struct SWindowData {
|
|||
CWindowOverridableVar<bool> syncFullscreen = true;
|
||||
CWindowOverridableVar<bool> tearing = false;
|
||||
CWindowOverridableVar<bool> xray = false;
|
||||
CWindowOverridableVar<bool> renderUnfocused = false;
|
||||
|
||||
CWindowOverridableVar<int> rounding;
|
||||
CWindowOverridableVar<int> borderSize;
|
||||
|
@ -201,6 +202,7 @@ struct SWindowRule {
|
|||
int bFullscreen = -1;
|
||||
int bPinned = -1;
|
||||
int bFocus = -1;
|
||||
std::string szFullscreenState = ""; // empty means any
|
||||
std::string szOnWorkspace = ""; // empty means any
|
||||
std::string szWorkspace = ""; // empty means any
|
||||
};
|
||||
|
@ -270,7 +272,7 @@ class CWindow {
|
|||
bool m_bDraggingTiled = false; // for dragging around tiled windows
|
||||
bool m_bWasMaximized = false;
|
||||
sFullscreenState m_sFullscreenState = {.internal = FSMODE_NONE, .client = FSMODE_NONE};
|
||||
uint64_t m_iMonitorID = -1;
|
||||
MONITORID m_iMonitorID = -1;
|
||||
std::string m_szTitle = "";
|
||||
std::string m_szClass = "";
|
||||
std::string m_szInitialTitle = "";
|
||||
|
@ -287,8 +289,6 @@ class CWindow {
|
|||
// XWayland stuff
|
||||
bool m_bIsX11 = false;
|
||||
PHLWINDOWREF m_pX11Parent;
|
||||
uint64_t m_iX11Type = 0;
|
||||
bool m_bIsModal = false;
|
||||
bool m_bX11DoesntWantBorders = false;
|
||||
bool m_bX11ShouldntFocus = false;
|
||||
float m_fX11SurfaceScaledBy = 1.f;
|
||||
|
@ -351,6 +351,10 @@ class CWindow {
|
|||
// animated tint
|
||||
CAnimatedVariable<float> m_fDimPercent;
|
||||
|
||||
// animate moving to an invisible workspace
|
||||
int m_iMonitorMovedFrom = -1; // -1 means not moving
|
||||
CAnimatedVariable<float> m_fMovingToWorkspaceAlpha;
|
||||
|
||||
// swallowing
|
||||
PHLWINDOWREF m_pSwallowed;
|
||||
|
||||
|
@ -358,8 +362,8 @@ class CWindow {
|
|||
bool m_bStayFocused = false;
|
||||
|
||||
// for toplevel monitor events
|
||||
uint64_t m_iLastToplevelMonitorID = -1;
|
||||
uint64_t m_iLastSurfaceMonitorID = -1;
|
||||
MONITORID m_iLastToplevelMonitorID = -1;
|
||||
MONITORID m_iLastSurfaceMonitorID = -1;
|
||||
|
||||
// for idle inhibiting windows
|
||||
eIdleInhibitMode m_eIdleInhibitMode = IDLEINHIBIT_NONE;
|
||||
|
@ -421,10 +425,11 @@ class CWindow {
|
|||
bool canBeTorn();
|
||||
void setSuspended(bool suspend);
|
||||
bool visibleOnMonitor(CMonitor* pMonitor);
|
||||
int workspaceID();
|
||||
WORKSPACEID workspaceID();
|
||||
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);
|
||||
|
@ -463,6 +468,8 @@ class CWindow {
|
|||
void warpCursor();
|
||||
PHLWINDOW getSwallower();
|
||||
void unsetWindowData(eOverridePriority priority);
|
||||
bool isX11OverrideRedirect();
|
||||
bool isModal();
|
||||
|
||||
// listeners
|
||||
void onAck(uint32_t serial);
|
||||
|
@ -492,7 +499,7 @@ class CWindow {
|
|||
// For hidden windows and stuff
|
||||
bool m_bHidden = false;
|
||||
bool m_bSuspended = false;
|
||||
int m_iLastWorkspace = WORKSPACE_INVALID;
|
||||
WORKSPACEID m_iLastWorkspace = WORKSPACE_INVALID;
|
||||
};
|
||||
|
||||
inline bool valid(PHLWINDOW w) {
|
||||
|
|
|
@ -5,27 +5,28 @@
|
|||
#include <hyprutils/string/String.hpp>
|
||||
using namespace Hyprutils::String;
|
||||
|
||||
PHLWORKSPACE CWorkspace::create(int id, int monitorID, std::string name, bool special, bool isEmtpy) {
|
||||
PHLWORKSPACE workspace = makeShared<CWorkspace>(id, monitorID, name, special, isEmtpy);
|
||||
PHLWORKSPACE CWorkspace::create(WORKSPACEID id, MONITORID monitorID, std::string name, bool special, bool isEmpty) {
|
||||
PHLWORKSPACE workspace = makeShared<CWorkspace>(id, monitorID, name, special, isEmpty);
|
||||
workspace->init(workspace);
|
||||
return workspace;
|
||||
}
|
||||
|
||||
CWorkspace::CWorkspace(int id, int monitorID, std::string name, bool special, bool isEmtpy) {
|
||||
CWorkspace::CWorkspace(WORKSPACEID id, MONITORID monitorID, std::string name, bool special, bool isEmpty) {
|
||||
m_iMonitorID = monitorID;
|
||||
m_iID = id;
|
||||
m_szName = name;
|
||||
m_bIsSpecialWorkspace = special;
|
||||
m_bWasCreatedEmtpy = isEmtpy;
|
||||
m_bWasCreatedEmpty = isEmpty;
|
||||
}
|
||||
|
||||
void CWorkspace::init(PHLWORKSPACE self) {
|
||||
m_pSelf = self;
|
||||
|
||||
m_vRenderOffset.create(m_bIsSpecialWorkspace ? g_pConfigManager->getAnimationPropertyConfig("specialWorkspace") : g_pConfigManager->getAnimationPropertyConfig("workspaces"),
|
||||
m_vRenderOffset.create(m_bIsSpecialWorkspace ? g_pConfigManager->getAnimationPropertyConfig("specialWorkspaceIn") :
|
||||
g_pConfigManager->getAnimationPropertyConfig("workspacesIn"),
|
||||
self, AVARDAMAGE_ENTIRE);
|
||||
m_fAlpha.create(AVARTYPE_FLOAT,
|
||||
m_bIsSpecialWorkspace ? g_pConfigManager->getAnimationPropertyConfig("specialWorkspace") : g_pConfigManager->getAnimationPropertyConfig("workspaces"), self,
|
||||
m_bIsSpecialWorkspace ? g_pConfigManager->getAnimationPropertyConfig("specialWorkspaceIn") : g_pConfigManager->getAnimationPropertyConfig("workspacesIn"), self,
|
||||
AVARDAMAGE_ENTIRE);
|
||||
m_fAlpha.setValueAndWarp(1.f);
|
||||
|
||||
|
@ -48,9 +49,9 @@ void CWorkspace::init(PHLWORKSPACE self) {
|
|||
const auto WORKSPACERULE = g_pConfigManager->getWorkspaceRuleFor(self);
|
||||
m_bPersistent = WORKSPACERULE.isPersistent;
|
||||
|
||||
if (self->m_bWasCreatedEmtpy)
|
||||
if (self->m_bWasCreatedEmpty)
|
||||
if (auto cmd = WORKSPACERULE.onCreatedEmptyRunCmd)
|
||||
g_pKeybindManager->spawn(*cmd);
|
||||
g_pKeybindManager->spawnWithRules(*cmd, self);
|
||||
|
||||
g_pEventManager->postEvent({"createworkspace", m_szName});
|
||||
g_pEventManager->postEvent({"createworkspacev2", std::format("{},{}", m_iID, m_szName)});
|
||||
|
@ -81,12 +82,19 @@ CWorkspace::~CWorkspace() {
|
|||
}
|
||||
|
||||
void CWorkspace::startAnim(bool in, bool left, bool instant) {
|
||||
if (!instant) {
|
||||
const std::string ANIMNAME = std::format("{}{}", m_bIsSpecialWorkspace ? "specialWorkspace" : "workspaces", in ? "In" : "Out");
|
||||
|
||||
m_fAlpha.m_pConfig = g_pConfigManager->getAnimationPropertyConfig(ANIMNAME);
|
||||
m_vRenderOffset.m_pConfig = g_pConfigManager->getAnimationPropertyConfig(ANIMNAME);
|
||||
}
|
||||
|
||||
const auto ANIMSTYLE = m_fAlpha.m_pConfig->pValues->internalStyle;
|
||||
static auto PWORKSPACEGAP = CConfigValue<Hyprlang::INT>("general:gaps_workspaces");
|
||||
|
||||
// set floating windows offset callbacks
|
||||
m_vRenderOffset.setUpdateCallback([&](void*) {
|
||||
for (auto& w : g_pCompositor->m_vWindows) {
|
||||
for (auto const& w : g_pCompositor->m_vWindows) {
|
||||
if (!validMapped(w) || w->workspaceID() != m_iID)
|
||||
continue;
|
||||
|
||||
|
@ -190,7 +198,7 @@ void CWorkspace::setActive(bool on) {
|
|||
; // empty until https://gitlab.freedesktop.org/wayland/wayland-protocols/-/merge_requests/40
|
||||
}
|
||||
|
||||
void CWorkspace::moveToMonitor(const int& id) {
|
||||
void CWorkspace::moveToMonitor(const MONITORID& id) {
|
||||
; // empty until https://gitlab.freedesktop.org/wayland/wayland-protocols/-/merge_requests/40
|
||||
}
|
||||
|
||||
|
@ -275,7 +283,7 @@ bool CWorkspace::matchesStaticSelector(const std::string& selector_) {
|
|||
i = std::min(NEXTSPACE, std::string::npos - 1);
|
||||
|
||||
if (cur == 'r') {
|
||||
int from = 0, to = 0;
|
||||
WORKSPACEID from = 0, to = 0;
|
||||
if (!prop.starts_with("r[") || !prop.ends_with("]")) {
|
||||
Debug::log(LOG, "Invalid selector {}", selector);
|
||||
return false;
|
||||
|
@ -365,7 +373,7 @@ bool CWorkspace::matchesStaticSelector(const std::string& selector_) {
|
|||
}
|
||||
|
||||
if (cur == 'w') {
|
||||
int from = 0, to = 0;
|
||||
WORKSPACEID from = 0, to = 0;
|
||||
if (!prop.starts_with("w[") || !prop.ends_with("]")) {
|
||||
Debug::log(LOG, "Invalid selector {}", selector);
|
||||
return false;
|
||||
|
@ -378,7 +386,7 @@ bool CWorkspace::matchesStaticSelector(const std::string& selector_) {
|
|||
bool wantsCountVisible = false;
|
||||
|
||||
int flagCount = 0;
|
||||
for (auto& flag : prop) {
|
||||
for (auto const& flag : prop) {
|
||||
if (flag == 't' && wantsOnlyTiled == -1) {
|
||||
wantsOnlyTiled = 1;
|
||||
flagCount++;
|
||||
|
@ -446,7 +454,7 @@ bool CWorkspace::matchesStaticSelector(const std::string& selector_) {
|
|||
return false;
|
||||
}
|
||||
|
||||
int count;
|
||||
WORKSPACEID count;
|
||||
if (wantsCountGroup)
|
||||
count = g_pCompositor->getGroupsOnWorkspace(m_iID, wantsOnlyTiled == -1 ? std::nullopt : std::optional<bool>((bool)wantsOnlyTiled),
|
||||
wantsCountVisible ? std::optional<bool>(wantsCountVisible) : std::nullopt);
|
||||
|
@ -506,7 +514,7 @@ bool CWorkspace::matchesStaticSelector(const std::string& selector_) {
|
|||
void CWorkspace::markInert() {
|
||||
m_bInert = true;
|
||||
m_iID = WORKSPACE_INVALID;
|
||||
m_iMonitorID = -1;
|
||||
m_iMonitorID = MONITOR_INVALID;
|
||||
m_bVisible = false;
|
||||
}
|
||||
|
||||
|
|
|
@ -17,16 +17,16 @@ class CWindow;
|
|||
|
||||
class CWorkspace {
|
||||
public:
|
||||
static PHLWORKSPACE create(int id, int monitorID, std::string name, bool special = false, bool isEmtpy = true);
|
||||
static PHLWORKSPACE create(WORKSPACEID id, MONITORID monitorID, std::string name, bool special = false, bool isEmpty = true);
|
||||
// use create() don't use this
|
||||
CWorkspace(int id, int monitorID, std::string name, bool special = false, bool isEmpty = true);
|
||||
CWorkspace(WORKSPACEID id, MONITORID monitorID, std::string name, bool special = false, bool isEmpty = true);
|
||||
~CWorkspace();
|
||||
|
||||
// Workspaces ID-based have IDs > 0
|
||||
// and workspaces name-based have IDs starting with -1337
|
||||
int m_iID = -1;
|
||||
WORKSPACEID m_iID = WORKSPACE_INVALID;
|
||||
std::string m_szName = "";
|
||||
uint64_t m_iMonitorID = -1;
|
||||
MONITORID m_iMonitorID = MONITOR_INVALID;
|
||||
// Previous workspace ID and name is stored during a workspace change, allowing travel
|
||||
// to the previous workspace.
|
||||
SWorkspaceIDName m_sPrevWorkspace, m_sPrevWorkspacePerMonitor;
|
||||
|
@ -57,7 +57,7 @@ class CWorkspace {
|
|||
// last monitor (used on reconnect)
|
||||
std::string m_szLastMonitor = "";
|
||||
|
||||
bool m_bWasCreatedEmtpy = true;
|
||||
bool m_bWasCreatedEmpty = true;
|
||||
|
||||
bool m_bPersistent = false;
|
||||
|
||||
|
@ -67,7 +67,7 @@ class CWorkspace {
|
|||
void startAnim(bool in, bool left, bool instant = false);
|
||||
void setActive(bool on);
|
||||
|
||||
void moveToMonitor(const int&);
|
||||
void moveToMonitor(const MONITORID&);
|
||||
|
||||
PHLWINDOW getLastFocusedWindow();
|
||||
void rememberPrevWorkspace(const PHLWORKSPACE& prevWorkspace);
|
||||
|
|
|
@ -119,7 +119,8 @@ void IKeyboard::setKeymap(const SStringRuleNames& rules) {
|
|||
if (IDX != XKB_MOD_INVALID)
|
||||
modifiersState.locked |= (uint32_t)1 << IDX;
|
||||
|
||||
updateModifiers(modifiersState.depressed, modifiersState.latched, modifiersState.locked, modifiersState.group);
|
||||
// 0 to avoid mods getting stuck if depressed during reload
|
||||
updateModifiers(0, 0, modifiersState.locked, modifiersState.group);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < LEDNAMES.size(); ++i) {
|
||||
|
@ -177,13 +178,18 @@ void IKeyboard::updateXKBTranslationState(xkb_keymap* const keymap) {
|
|||
if (xkbState)
|
||||
xkb_state_unref(xkbState);
|
||||
|
||||
if (xkbSymState)
|
||||
xkb_state_unref(xkbSymState);
|
||||
|
||||
xkbState = nullptr;
|
||||
xkbStaticState = nullptr;
|
||||
xkbSymState = nullptr;
|
||||
|
||||
if (keymap) {
|
||||
Debug::log(LOG, "Updating keyboard {:x}'s translation state from a provided keymap", (uintptr_t)this);
|
||||
xkbStaticState = xkb_state_new(keymap);
|
||||
xkbState = xkb_state_new(keymap);
|
||||
xkbSymState = xkb_state_new(keymap);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -229,6 +235,7 @@ void IKeyboard::updateXKBTranslationState(xkb_keymap* const keymap) {
|
|||
|
||||
xkbState = xkb_state_new(KEYMAP);
|
||||
xkbStaticState = xkb_state_new(KEYMAP);
|
||||
xkbSymState = xkb_state_new(KEYMAP);
|
||||
|
||||
xkb_keymap_unref(KEYMAP);
|
||||
xkb_context_unref(PCONTEXT);
|
||||
|
@ -251,6 +258,7 @@ void IKeyboard::updateXKBTranslationState(xkb_keymap* const keymap) {
|
|||
|
||||
xkbState = xkb_state_new(NEWKEYMAP);
|
||||
xkbStaticState = xkb_state_new(NEWKEYMAP);
|
||||
xkbSymState = xkb_state_new(NEWKEYMAP);
|
||||
|
||||
xkb_keymap_unref(NEWKEYMAP);
|
||||
xkb_context_unref(PCONTEXT);
|
||||
|
@ -331,6 +339,9 @@ void IKeyboard::updateModifiers(uint32_t depressed, uint32_t latched, uint32_t l
|
|||
|
||||
xkb_state_update_mask(xkbState, depressed, latched, locked, 0, 0, group);
|
||||
|
||||
if (xkbSymState)
|
||||
xkb_state_update_mask(xkbSymState, 0, 0, 0, 0, 0, group);
|
||||
|
||||
if (!updateModifiersState())
|
||||
return;
|
||||
|
||||
|
@ -381,6 +392,9 @@ void IKeyboard::updateXkbStateWithKey(uint32_t xkbKey, bool pressed) {
|
|||
xkb_state_update_key(xkbState, xkbKey, pressed ? XKB_KEY_DOWN : XKB_KEY_UP);
|
||||
|
||||
if (updateModifiersState()) {
|
||||
if (xkbSymState)
|
||||
xkb_state_update_mask(xkbSymState, 0, 0, 0, 0, 0, modifiersState.group);
|
||||
|
||||
keyboardEvents.modifiers.emit(SModifiersEvent{
|
||||
.depressed = modifiersState.depressed,
|
||||
.latched = modifiersState.latched,
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include "IHID.hpp"
|
||||
#include "../helpers/WLListener.hpp"
|
||||
#include "../macros.hpp"
|
||||
#include "../helpers/math/Math.hpp"
|
||||
|
||||
|
@ -83,7 +82,8 @@ class IKeyboard : public IHID {
|
|||
bool keymapOverridden = false;
|
||||
|
||||
xkb_layout_index_t activeLayout = 0;
|
||||
xkb_state * xkbState = nullptr, *xkbStaticState /* Static state: never gets modifiers or layout changes sent, used for keybinds. */ = nullptr;
|
||||
xkb_state * xkbState = nullptr, *xkbStaticState /* Static state: never gets modifiers or layout changes sent, used for keybinds. */ = nullptr,
|
||||
*xkbSymState = nullptr /* Same as static but gets layouts */;
|
||||
xkb_keymap* xkbKeymap = nullptr;
|
||||
|
||||
struct {
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include "IHID.hpp"
|
||||
#include "../helpers/WLListener.hpp"
|
||||
#include "../macros.hpp"
|
||||
#include "../helpers/math/Math.hpp"
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include "IHID.hpp"
|
||||
#include "../helpers/WLListener.hpp"
|
||||
#include "../macros.hpp"
|
||||
#include "../helpers/math/Math.hpp"
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include "IHID.hpp"
|
||||
#include "../helpers/WLListener.hpp"
|
||||
#include "../macros.hpp"
|
||||
#include "../helpers/math/Math.hpp"
|
||||
#include "../helpers/math/Math.hpp"
|
||||
|
|
|
@ -27,7 +27,6 @@ namespace Events {
|
|||
|
||||
// Monitor part 2 the sequel
|
||||
DYNLISTENFUNC(monitorFrame);
|
||||
DYNLISTENFUNC(monitorDestroy);
|
||||
DYNLISTENFUNC(monitorStateRequest);
|
||||
DYNLISTENFUNC(monitorDamage);
|
||||
DYNLISTENFUNC(monitorNeedsFrame);
|
||||
|
|
|
@ -85,31 +85,6 @@ void Events::listener_monitorFrame(void* owner, void* data) {
|
|||
}
|
||||
}
|
||||
|
||||
void Events::listener_monitorDestroy(void* owner, void* data) {
|
||||
CMonitor* pMonitor = (CMonitor*)owner;
|
||||
|
||||
for (auto& m : g_pCompositor->m_vRealMonitors) {
|
||||
if (m->output == pMonitor->output) {
|
||||
pMonitor = m.get();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!pMonitor)
|
||||
return;
|
||||
|
||||
Debug::log(LOG, "Destroy called for monitor {}", pMonitor->output->name);
|
||||
|
||||
pMonitor->onDisconnect(true);
|
||||
|
||||
pMonitor->output = nullptr;
|
||||
pMonitor->m_bRenderingInitPassed = false;
|
||||
|
||||
Debug::log(LOG, "Removing monitor {} from realMonitors", pMonitor->szName);
|
||||
|
||||
std::erase_if(g_pCompositor->m_vRealMonitors, [&](SP<CMonitor>& el) { return el.get() == pMonitor; });
|
||||
}
|
||||
|
||||
void Events::listener_monitorNeedsFrame(void* owner, void* data) {
|
||||
const auto PMONITOR = (CMonitor*)owner;
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "../protocols/core/Compositor.hpp"
|
||||
#include "../protocols/ToplevelExport.hpp"
|
||||
#include "../xwayland/XSurface.hpp"
|
||||
#include "managers/PointerManager.hpp"
|
||||
|
||||
#include <hyprutils/string/String.hpp>
|
||||
using namespace Hyprutils::String;
|
||||
|
@ -120,7 +121,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
|||
PWINDOW->m_bRequestsFloat = true;
|
||||
}
|
||||
|
||||
PWINDOW->m_bX11ShouldntFocus = PWINDOW->m_bX11ShouldntFocus || (PWINDOW->m_bIsX11 && PWINDOW->m_iX11Type == 2 && !PWINDOW->m_pXWaylandSurface->wantsFocus());
|
||||
PWINDOW->m_bX11ShouldntFocus = PWINDOW->m_bX11ShouldntFocus || (PWINDOW->m_bIsX11 && PWINDOW->isX11OverrideRedirect() && !PWINDOW->m_pXWaylandSurface->wantsFocus());
|
||||
|
||||
if (PWORKSPACE->m_bDefaultFloating)
|
||||
PWINDOW->m_bIsFloating = true;
|
||||
|
@ -139,7 +140,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
|||
if (PWINDOW->m_bWantsInitialFullscreen || (PWINDOW->m_bIsX11 && PWINDOW->m_pXWaylandSurface->fullscreen))
|
||||
requestedClientFSMode = FSMODE_FULLSCREEN;
|
||||
|
||||
for (auto& r : PWINDOW->m_vMatchedRules) {
|
||||
for (auto const& r : PWINDOW->m_vMatchedRules) {
|
||||
if (r.szRule.starts_with("monitor")) {
|
||||
try {
|
||||
const auto MONITORSTR = trim(r.szRule.substr(r.szRule.find(' ')));
|
||||
|
@ -148,7 +149,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
|||
PWINDOW->m_iMonitorID = PMONITOR->ID;
|
||||
} else {
|
||||
if (isNumber(MONITORSTR)) {
|
||||
const long int MONITOR = std::stoi(MONITORSTR);
|
||||
const MONITORID MONITOR = std::stoi(MONITORSTR);
|
||||
if (!g_pCompositor->getMonitorFromID(MONITOR))
|
||||
PWINDOW->m_iMonitorID = 0;
|
||||
else
|
||||
|
@ -322,11 +323,11 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
|||
PWINDOW->updateWindowData();
|
||||
|
||||
if (PWINDOW->m_bIsFloating) {
|
||||
g_pLayoutManager->getCurrentLayout()->onWindowCreatedFloating(PWINDOW);
|
||||
g_pLayoutManager->getCurrentLayout()->onWindowCreated(PWINDOW);
|
||||
PWINDOW->m_bCreatedOverFullscreen = true;
|
||||
|
||||
// size and move rules
|
||||
for (auto& r : PWINDOW->m_vMatchedRules) {
|
||||
for (auto const& r : PWINDOW->m_vMatchedRules) {
|
||||
if (r.szRule.starts_with("size")) {
|
||||
try {
|
||||
const auto VALUE = r.szRule.substr(r.szRule.find(' ') + 1);
|
||||
|
@ -345,6 +346,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
|||
Debug::log(LOG, "Rule size, applying to {}", PWINDOW);
|
||||
|
||||
PWINDOW->m_vRealSize = Vector2D(SIZEX, SIZEY);
|
||||
PWINDOW->m_vPseudoSize = PWINDOW->m_vRealSize.goal();
|
||||
g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goal());
|
||||
|
||||
PWINDOW->setHidden(false);
|
||||
|
@ -449,7 +451,35 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
|||
} else {
|
||||
g_pLayoutManager->getCurrentLayout()->onWindowCreated(PWINDOW);
|
||||
|
||||
// Set the pseudo size here too so that it doesnt end up being 0x0
|
||||
bool setPseudo = false;
|
||||
|
||||
for (auto const& r : PWINDOW->m_vMatchedRules) {
|
||||
if (r.szRule.starts_with("size")) {
|
||||
try {
|
||||
const auto VALUE = r.szRule.substr(r.szRule.find(' ') + 1);
|
||||
const auto SIZEXSTR = VALUE.substr(0, VALUE.find(' '));
|
||||
const auto SIZEYSTR = VALUE.substr(VALUE.find(' ') + 1);
|
||||
|
||||
const auto MAXSIZE = g_pXWaylandManager->getMaxSizeForWindow(PWINDOW);
|
||||
|
||||
const auto SIZEX = SIZEXSTR == "max" ?
|
||||
std::clamp(MAXSIZE.x, 20.0, PMONITOR->vecSize.x) :
|
||||
(!SIZEXSTR.contains('%') ? std::stoi(SIZEXSTR) : std::stof(SIZEXSTR.substr(0, SIZEXSTR.length() - 1)) * 0.01 * PMONITOR->vecSize.x);
|
||||
const auto SIZEY = SIZEYSTR == "max" ?
|
||||
std::clamp(MAXSIZE.y, 20.0, PMONITOR->vecSize.y) :
|
||||
(!SIZEYSTR.contains('%') ? std::stoi(SIZEYSTR) : std::stof(SIZEYSTR.substr(0, SIZEYSTR.length() - 1)) * 0.01 * PMONITOR->vecSize.y);
|
||||
|
||||
Debug::log(LOG, "Rule size (tiled), applying to {}", PWINDOW);
|
||||
|
||||
setPseudo = true;
|
||||
PWINDOW->m_vPseudoSize = Vector2D(SIZEX, SIZEY);
|
||||
|
||||
PWINDOW->setHidden(false);
|
||||
} catch (...) { Debug::log(LOG, "Rule size failed, rule: {} -> {}", r.szRule, r.szValue); }
|
||||
}
|
||||
}
|
||||
|
||||
if (!setPseudo)
|
||||
PWINDOW->m_vPseudoSize = PWINDOW->m_vRealSize.goal() - Vector2D(10, 10);
|
||||
}
|
||||
|
||||
|
@ -477,7 +507,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
|||
}
|
||||
|
||||
if (!PWINDOW->m_sWindowData.noFocus.valueOrDefault() && !PWINDOW->m_bNoInitialFocus &&
|
||||
(PWINDOW->m_iX11Type != 2 || (PWINDOW->m_bIsX11 && PWINDOW->m_pXWaylandSurface->wantsFocus())) && !workspaceSilent && (!PFORCEFOCUS || PFORCEFOCUS == PWINDOW) &&
|
||||
(!PWINDOW->isX11OverrideRedirect() || (PWINDOW->m_bIsX11 && PWINDOW->m_pXWaylandSurface->wantsFocus())) && !workspaceSilent && (!PFORCEFOCUS || PFORCEFOCUS == PWINDOW) &&
|
||||
!g_pInputManager->isConstrained()) {
|
||||
g_pCompositor->focusWindow(PWINDOW);
|
||||
PWINDOW->m_fActiveInactiveAlpha.setValueAndWarp(*PACTIVEALPHA);
|
||||
|
@ -577,7 +607,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
|||
|
||||
g_pCompositor->updateWorkspaceWindows(PWINDOW->workspaceID());
|
||||
|
||||
if (PMONITOR && PWINDOW->m_iX11Type == 2)
|
||||
if (PMONITOR && PWINDOW->isX11OverrideRedirect())
|
||||
PWINDOW->m_fX11SurfaceScaledBy = PMONITOR->scale;
|
||||
}
|
||||
|
||||
|
@ -648,7 +678,12 @@ void Events::listener_unmapWindow(void* owner, void* data) {
|
|||
|
||||
// refocus on a new window if needed
|
||||
if (wasLastWindow) {
|
||||
const auto PWINDOWCANDIDATE = g_pLayoutManager->getCurrentLayout()->getNextWindowCandidate(PWINDOW);
|
||||
static auto FOCUSONCLOSE = CConfigValue<Hyprlang::INT>("input:focus_on_close");
|
||||
PHLWINDOW PWINDOWCANDIDATE = nullptr;
|
||||
if (*FOCUSONCLOSE)
|
||||
PWINDOWCANDIDATE = (g_pCompositor->vectorToWindowUnified(g_pInputManager->getMouseCoordsInternal(), RESERVED_EXTENTS | INPUT_EXTENTS | ALLOW_FLOATING));
|
||||
else
|
||||
PWINDOWCANDIDATE = g_pLayoutManager->getCurrentLayout()->getNextWindowCandidate(PWINDOW);
|
||||
|
||||
Debug::log(LOG, "On closed window, new focused candidate is {}", PWINDOWCANDIDATE);
|
||||
|
||||
|
@ -717,41 +752,35 @@ void Events::listener_commitWindow(void* owner, void* data) {
|
|||
const auto MINSIZE = PWINDOW->m_pXDGSurface->toplevel->current.minSize;
|
||||
const auto MAXSIZE = PWINDOW->m_pXDGSurface->toplevel->current.maxSize;
|
||||
|
||||
if (MAXSIZE > Vector2D{1, 1}) {
|
||||
const auto REALSIZE = PWINDOW->m_vRealSize.goal();
|
||||
Vector2D newSize = REALSIZE;
|
||||
|
||||
if (MAXSIZE.x < newSize.x)
|
||||
newSize.x = MAXSIZE.x;
|
||||
if (MAXSIZE.y < newSize.y)
|
||||
newSize.y = MAXSIZE.y;
|
||||
if (MINSIZE.x > newSize.x)
|
||||
newSize.x = MINSIZE.x;
|
||||
if (MINSIZE.y > newSize.y)
|
||||
newSize.y = MINSIZE.y;
|
||||
|
||||
const Vector2D DELTA = REALSIZE - newSize;
|
||||
|
||||
PWINDOW->m_vRealPosition = PWINDOW->m_vRealPosition.goal() + DELTA / 2.0;
|
||||
PWINDOW->m_vRealSize = newSize;
|
||||
g_pXWaylandManager->setWindowSize(PWINDOW, newSize);
|
||||
PWINDOW->clampWindowSize(MINSIZE, MAXSIZE > Vector2D{1, 1} ? std::optional<Vector2D>{MAXSIZE} : std::nullopt);
|
||||
g_pHyprRenderer->damageWindow(PWINDOW);
|
||||
}
|
||||
}
|
||||
|
||||
if (!PWINDOW->m_pWorkspace->m_bVisible)
|
||||
return;
|
||||
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID);
|
||||
|
||||
PMONITOR->debugLastPresentation(g_pSeatManager->isPointerFrameCommit ? "listener_commitWindow skip" : "listener_commitWindow");
|
||||
if (g_pSeatManager->isPointerFrameCommit) {
|
||||
g_pSeatManager->isPointerFrameSkipped = false;
|
||||
g_pSeatManager->isPointerFrameCommit = false;
|
||||
} else
|
||||
g_pHyprRenderer->damageSurface(PWINDOW->m_pWLSurface->resource(), PWINDOW->m_vRealPosition.goal().x, PWINDOW->m_vRealPosition.goal().y,
|
||||
PWINDOW->m_bIsX11 ? 1.0 / PWINDOW->m_fX11SurfaceScaledBy : 1.0);
|
||||
|
||||
if (g_pSeatManager->isPointerFrameSkipped) {
|
||||
g_pPointerManager->sendStoredMovement();
|
||||
g_pSeatManager->sendPointerFrame();
|
||||
g_pSeatManager->isPointerFrameCommit = true;
|
||||
}
|
||||
|
||||
if (!PWINDOW->m_bIsX11) {
|
||||
PWINDOW->m_pSubsurfaceHead->recheckDamageForSubsurfaces();
|
||||
PWINDOW->m_pPopupHead->recheckTree();
|
||||
}
|
||||
|
||||
// tearing: if solitary, redraw it. This still might be a single surface window
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID);
|
||||
if (PMONITOR && PMONITOR->solitaryClient.lock() == PWINDOW && PWINDOW->canBeTorn() && PMONITOR->tearingState.canTear && PWINDOW->m_pWLSurface->resource()->current.texture) {
|
||||
CRegion damageBox{PWINDOW->m_pWLSurface->resource()->accumulateCurrentBufferDamage()};
|
||||
|
||||
|
@ -811,7 +840,7 @@ void Events::listener_activateX11(void* owner, void* data) {
|
|||
|
||||
Debug::log(LOG, "X11 Activate request for window {}", PWINDOW);
|
||||
|
||||
if (PWINDOW->m_iX11Type == 2) {
|
||||
if (PWINDOW->isX11OverrideRedirect()) {
|
||||
|
||||
Debug::log(LOG, "Unmanaged X11 {} requests activate", PWINDOW);
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ void CBezierCurve::setup(std::vector<Vector2D>* pVec) {
|
|||
|
||||
m_dPoints.emplace_back(Vector2D(0, 0));
|
||||
|
||||
for (auto& p : *pVec) {
|
||||
for (auto const& p : *pVec) {
|
||||
m_dPoints.push_back(p);
|
||||
}
|
||||
|
||||
|
|
54
src/helpers/ByteOperations.hpp
Normal file
|
@ -0,0 +1,54 @@
|
|||
#pragma once
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
#define ULL unsigned long long
|
||||
#define LD long double
|
||||
|
||||
constexpr ULL operator""_kB(const ULL BYTES) {
|
||||
return BYTES * 1024;
|
||||
}
|
||||
constexpr ULL operator""_MB(const ULL BYTES) {
|
||||
return BYTES * 1024 * 1024;
|
||||
}
|
||||
constexpr ULL operator""_GB(const ULL BYTES) {
|
||||
return BYTES * 1024 * 1024 * 1024;
|
||||
}
|
||||
constexpr ULL operator""_TB(const ULL BYTES) {
|
||||
return BYTES * 1024 * 1024 * 1024 * 1024;
|
||||
}
|
||||
constexpr LD operator""_kB(const LD BYTES) {
|
||||
return BYTES * 1024;
|
||||
}
|
||||
constexpr LD operator""_MB(const LD BYTES) {
|
||||
return BYTES * 1024 * 1024;
|
||||
}
|
||||
constexpr LD operator""_GB(const LD BYTES) {
|
||||
return BYTES * 1024 * 1024 * 1024;
|
||||
}
|
||||
constexpr LD operator""_TB(const LD BYTES) {
|
||||
return BYTES * 1024 * 1024 * 1024 * 1024;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
using __acceptable_byte_operation_type = typename std::enable_if<std::is_trivially_constructible<T, ULL>::value || std::is_trivially_constructible<T, LD>::value>::type;
|
||||
|
||||
template <typename X, typename = __acceptable_byte_operation_type<X>>
|
||||
constexpr X kBtoBytes(const X kB) {
|
||||
return kB * 1024;
|
||||
}
|
||||
template <typename X, typename = __acceptable_byte_operation_type<X>>
|
||||
constexpr X MBtoBytes(const X MB) {
|
||||
return MB * 1024 * 1024;
|
||||
}
|
||||
template <typename X, typename = __acceptable_byte_operation_type<X>>
|
||||
constexpr X GBtoBytes(const X GB) {
|
||||
return GB * 1024 * 1024 * 1024;
|
||||
}
|
||||
template <typename X, typename = __acceptable_byte_operation_type<X>>
|
||||
constexpr X TBtoBytes(const X TB) {
|
||||
return TB * 1024 * 1024 * 1024 * 1024;
|
||||
}
|
||||
|
||||
#undef ULL
|
||||
#undef LD
|
|
@ -21,6 +21,6 @@ CColor::CColor(uint64_t hex) {
|
|||
this->a = ALPHA(hex);
|
||||
}
|
||||
|
||||
uint32_t CColor::getAsHex() {
|
||||
uint32_t CColor::getAsHex() const {
|
||||
return (uint32_t)(a * 255.f) * 0x1000000 + (uint32_t)(r * 255.f) * 0x10000 + (uint32_t)(g * 255.f) * 0x100 + (uint32_t)(b * 255.f) * 0x1;
|
||||
}
|
|
@ -10,7 +10,8 @@ class CColor {
|
|||
|
||||
float r = 0, g = 0, b = 0, a = 1.f;
|
||||
|
||||
uint32_t getAsHex();
|
||||
// AR32
|
||||
uint32_t getAsHex() const;
|
||||
|
||||
CColor operator-(const CColor& c2) const {
|
||||
return CColor(r - c2.r, g - c2.g, b - c2.b, a - c2.a);
|
||||
|
|
|
@ -252,7 +252,7 @@ DRMFormat FormatUtils::shmToDRM(SHMFormat shm) {
|
|||
}
|
||||
|
||||
const SPixelFormat* FormatUtils::getPixelFormatFromDRM(DRMFormat drm) {
|
||||
for (auto& fmt : GLES3_FORMATS) {
|
||||
for (auto const& fmt : GLES3_FORMATS) {
|
||||
if (fmt.drmFormat == drm)
|
||||
return &fmt;
|
||||
}
|
||||
|
@ -261,7 +261,7 @@ const SPixelFormat* FormatUtils::getPixelFormatFromDRM(DRMFormat drm) {
|
|||
}
|
||||
|
||||
const SPixelFormat* FormatUtils::getPixelFormatFromGL(uint32_t glFormat, uint32_t glType, bool alpha) {
|
||||
for (auto& fmt : GLES3_FORMATS) {
|
||||
for (auto const& fmt : GLES3_FORMATS) {
|
||||
if (fmt.glFormat == (int)glFormat && fmt.glType == (int)glType && fmt.withAlpha == alpha)
|
||||
return &fmt;
|
||||
}
|
||||
|
|
|
@ -180,7 +180,7 @@ void handleNoop(struct wl_listener* listener, void* data) {
|
|||
|
||||
std::string escapeJSONStrings(const std::string& str) {
|
||||
std::ostringstream oss;
|
||||
for (auto& c : str) {
|
||||
for (auto const& c : str) {
|
||||
switch (c) {
|
||||
case '"': oss << "\\\""; break;
|
||||
case '\\': oss << "\\\\"; break;
|
||||
|
@ -249,17 +249,17 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) {
|
|||
return {WORKSPACE_INVALID};
|
||||
}
|
||||
|
||||
std::set<int> invalidWSes;
|
||||
std::set<WORKSPACEID> invalidWSes;
|
||||
if (same_mon) {
|
||||
for (auto& rule : g_pConfigManager->getAllWorkspaceRules()) {
|
||||
for (auto const& rule : g_pConfigManager->getAllWorkspaceRules()) {
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromName(rule.monitor);
|
||||
if (PMONITOR && (PMONITOR->ID != g_pCompositor->m_pLastMonitor->ID))
|
||||
invalidWSes.insert(rule.workspaceId);
|
||||
}
|
||||
}
|
||||
|
||||
int id = next ? g_pCompositor->m_pLastMonitor->activeWorkspaceID() : 0;
|
||||
while (++id < INT_MAX) {
|
||||
WORKSPACEID id = next ? g_pCompositor->m_pLastMonitor->activeWorkspaceID() : 0;
|
||||
while (++id < LONG_MAX) {
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(id);
|
||||
if (!invalidWSes.contains(id) && (!PWORKSPACE || g_pCompositor->getWindowsOnWorkspace(id) == 0)) {
|
||||
result.id = id;
|
||||
|
@ -296,18 +296,18 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) {
|
|||
|
||||
result.id = (int)PLUSMINUSRESULT.value();
|
||||
|
||||
int remains = (int)result.id;
|
||||
WORKSPACEID remains = result.id;
|
||||
|
||||
std::set<int> invalidWSes;
|
||||
std::set<WORKSPACEID> invalidWSes;
|
||||
|
||||
// Collect all the workspaces we can't jump to.
|
||||
for (auto& ws : g_pCompositor->m_vWorkspaces) {
|
||||
for (auto const& ws : g_pCompositor->m_vWorkspaces) {
|
||||
if (ws->m_bIsSpecialWorkspace || (ws->m_iMonitorID != g_pCompositor->m_pLastMonitor->ID)) {
|
||||
// Can't jump to this workspace
|
||||
invalidWSes.insert(ws->m_iID);
|
||||
}
|
||||
}
|
||||
for (auto& rule : g_pConfigManager->getAllWorkspaceRules()) {
|
||||
for (auto const& rule : g_pConfigManager->getAllWorkspaceRules()) {
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromName(rule.monitor);
|
||||
if (!PMONITOR || PMONITOR->ID == g_pCompositor->m_pLastMonitor->ID) {
|
||||
// Can't be invalid
|
||||
|
@ -318,8 +318,8 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) {
|
|||
}
|
||||
|
||||
// Prepare all named workspaces in case when we need them
|
||||
std::vector<int> namedWSes;
|
||||
for (auto& ws : g_pCompositor->m_vWorkspaces) {
|
||||
std::vector<WORKSPACEID> namedWSes;
|
||||
for (auto const& ws : g_pCompositor->m_vWorkspaces) {
|
||||
if (ws->m_bIsSpecialWorkspace || (ws->m_iMonitorID != g_pCompositor->m_pLastMonitor->ID) || ws->m_iID >= 0)
|
||||
continue;
|
||||
|
||||
|
@ -347,19 +347,19 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) {
|
|||
} else {
|
||||
|
||||
// Just take a blind guess at where we'll probably end up
|
||||
int activeWSID = g_pCompositor->m_pLastMonitor->activeWorkspace ? g_pCompositor->m_pLastMonitor->activeWorkspace->m_iID : 1;
|
||||
int predictedWSID = activeWSID + remains;
|
||||
WORKSPACEID activeWSID = g_pCompositor->m_pLastMonitor->activeWorkspace ? g_pCompositor->m_pLastMonitor->activeWorkspace->m_iID : 1;
|
||||
WORKSPACEID predictedWSID = activeWSID + remains;
|
||||
int remainingWSes = 0;
|
||||
char walkDir = in[1];
|
||||
|
||||
// sanitize. 0 means invalid oob in -
|
||||
predictedWSID = std::max(predictedWSID, 0);
|
||||
predictedWSID = std::max(predictedWSID, static_cast<int64_t>(0));
|
||||
|
||||
// Count how many invalidWSes are in between (how bad the prediction was)
|
||||
int beginID = in[1] == '+' ? activeWSID + 1 : predictedWSID;
|
||||
int endID = in[1] == '+' ? predictedWSID : activeWSID;
|
||||
WORKSPACEID beginID = in[1] == '+' ? activeWSID + 1 : predictedWSID;
|
||||
WORKSPACEID endID = in[1] == '+' ? predictedWSID : activeWSID;
|
||||
auto begin = invalidWSes.upper_bound(beginID - 1); // upper_bound is >, we want >=
|
||||
for (auto it = begin; *it <= endID && it != invalidWSes.end(); it++) {
|
||||
for (auto it = begin; it != invalidWSes.end() && *it <= endID; it++) {
|
||||
remainingWSes++;
|
||||
}
|
||||
|
||||
|
@ -367,7 +367,7 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) {
|
|||
if (activeWSID < 0) {
|
||||
// Behaviour similar to 'm'
|
||||
// Find current
|
||||
int currentItem = -1;
|
||||
size_t currentItem = -1;
|
||||
for (size_t i = 0; i < namedWSes.size(); i++) {
|
||||
if (namedWSes[i] == activeWSID) {
|
||||
currentItem = i;
|
||||
|
@ -376,15 +376,15 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) {
|
|||
}
|
||||
|
||||
currentItem += remains;
|
||||
currentItem = std::max(currentItem, 0);
|
||||
if (currentItem >= (int)namedWSes.size()) {
|
||||
currentItem = std::max(currentItem, static_cast<size_t>(0));
|
||||
if (currentItem >= namedWSes.size()) {
|
||||
// At the seam between namedWSes and normal WSes. Behave like r+[diff] at imaginary ws 0
|
||||
int diff = currentItem - (namedWSes.size() - 1);
|
||||
size_t diff = currentItem - (namedWSes.size() - 1);
|
||||
predictedWSID = diff;
|
||||
int beginID = 1;
|
||||
int endID = predictedWSID;
|
||||
WORKSPACEID beginID = 1;
|
||||
WORKSPACEID endID = predictedWSID;
|
||||
auto begin = invalidWSes.upper_bound(beginID - 1); // upper_bound is >, we want >=
|
||||
for (auto it = begin; *it <= endID && it != invalidWSes.end(); it++) {
|
||||
for (auto it = begin; it != invalidWSes.end() && *it <= endID; it++) {
|
||||
remainingWSes++;
|
||||
}
|
||||
walkDir = '+';
|
||||
|
@ -397,10 +397,10 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) {
|
|||
|
||||
// Go in the search direction for remainingWSes
|
||||
// The performance impact is directly proportional to the number of open and bound workspaces
|
||||
int finalWSID = predictedWSID;
|
||||
WORKSPACEID finalWSID = predictedWSID;
|
||||
if (walkDir == '-') {
|
||||
int beginID = finalWSID;
|
||||
int curID = finalWSID;
|
||||
WORKSPACEID beginID = finalWSID;
|
||||
WORKSPACEID curID = finalWSID;
|
||||
while (--curID > 0 && remainingWSes > 0) {
|
||||
if (!invalidWSes.contains(curID)) {
|
||||
remainingWSes--;
|
||||
|
@ -411,9 +411,9 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) {
|
|||
if (namedWSes.size()) {
|
||||
// Go to the named workspaces
|
||||
// Need remainingWSes more
|
||||
int namedWSIdx = namedWSes.size() - remainingWSes;
|
||||
auto namedWSIdx = namedWSes.size() - remainingWSes;
|
||||
// Sanitze
|
||||
namedWSIdx = std::clamp(namedWSIdx, 0, (int)namedWSes.size() - 1);
|
||||
namedWSIdx = std::clamp(namedWSIdx, static_cast<size_t>(0), namedWSes.size() - static_cast<size_t>(1));
|
||||
finalWSID = namedWSes[namedWSIdx];
|
||||
} else {
|
||||
// Couldn't find valid workspace in negative direction, search last first one back up positive direction
|
||||
|
@ -425,7 +425,7 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) {
|
|||
}
|
||||
}
|
||||
if (walkDir == '+') {
|
||||
int curID = finalWSID;
|
||||
WORKSPACEID curID = finalWSID;
|
||||
while (++curID < INT32_MAX && remainingWSes > 0) {
|
||||
if (!invalidWSes.contains(curID)) {
|
||||
remainingWSes--;
|
||||
|
@ -462,8 +462,8 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) {
|
|||
// result now has +/- what we should move on mon
|
||||
int remains = (int)result.id;
|
||||
|
||||
std::vector<int> validWSes;
|
||||
for (auto& ws : g_pCompositor->m_vWorkspaces) {
|
||||
std::vector<WORKSPACEID> validWSes;
|
||||
for (auto const& ws : g_pCompositor->m_vWorkspaces) {
|
||||
if (ws->m_bIsSpecialWorkspace || (ws->m_iMonitorID != g_pCompositor->m_pLastMonitor->ID && !onAllMonitors))
|
||||
continue;
|
||||
|
||||
|
@ -472,7 +472,7 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) {
|
|||
|
||||
std::sort(validWSes.begin(), validWSes.end());
|
||||
|
||||
int currentItem = -1;
|
||||
ssize_t currentItem = -1;
|
||||
|
||||
if (absolute) {
|
||||
// 1-index
|
||||
|
@ -481,7 +481,7 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) {
|
|||
// clamp
|
||||
if (currentItem < 0) {
|
||||
currentItem = 0;
|
||||
} else if (currentItem >= (int)validWSes.size()) {
|
||||
} else if (currentItem >= (ssize_t)validWSes.size()) {
|
||||
currentItem = validWSes.size() - 1;
|
||||
}
|
||||
} else {
|
||||
|
@ -489,8 +489,8 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) {
|
|||
remains = remains < 0 ? -((-remains) % validWSes.size()) : remains % validWSes.size();
|
||||
|
||||
// get the current item
|
||||
int activeWSID = g_pCompositor->m_pLastMonitor->activeWorkspace ? g_pCompositor->m_pLastMonitor->activeWorkspace->m_iID : 1;
|
||||
for (size_t i = 0; i < validWSes.size(); i++) {
|
||||
WORKSPACEID activeWSID = g_pCompositor->m_pLastMonitor->activeWorkspace ? g_pCompositor->m_pLastMonitor->activeWorkspace->m_iID : 1;
|
||||
for (ssize_t i = 0; i < (ssize_t)validWSes.size(); i++) {
|
||||
if (validWSes[i] == activeWSID) {
|
||||
currentItem = i;
|
||||
break;
|
||||
|
@ -501,7 +501,7 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) {
|
|||
currentItem += remains;
|
||||
|
||||
// sanitize
|
||||
if (currentItem >= (int)validWSes.size()) {
|
||||
if (currentItem >= (ssize_t)validWSes.size()) {
|
||||
currentItem = currentItem % validWSes.size();
|
||||
} else if (currentItem < 0) {
|
||||
currentItem = validWSes.size() + currentItem;
|
||||
|
@ -547,7 +547,7 @@ std::optional<std::string> cleanCmdForWorkspace(const std::string& inWorkspaceNa
|
|||
const std::string workspaceRule = "workspace " + inWorkspaceName;
|
||||
|
||||
if (cmd[0] == '[') {
|
||||
const int closingBracketIdx = cmd.find_last_of(']');
|
||||
const auto closingBracketIdx = cmd.find_last_of(']');
|
||||
auto tmpRules = cmd.substr(1, closingBracketIdx - 1);
|
||||
cmd = cmd.substr(closingBracketIdx + 1);
|
||||
|
||||
|
@ -628,27 +628,6 @@ void logSystemInfo() {
|
|||
Debug::log(NONE, "{}", execAndGet("cat /etc/os-release"));
|
||||
}
|
||||
|
||||
void matrixProjection(float mat[9], int w, int h, wl_output_transform tr) {
|
||||
memset(mat, 0, sizeof(*mat) * 9);
|
||||
|
||||
const float* t = transforms[tr];
|
||||
float x = 2.0f / w;
|
||||
float y = 2.0f / h;
|
||||
|
||||
// Rotation + reflection
|
||||
mat[0] = x * t[0];
|
||||
mat[1] = x * t[1];
|
||||
mat[3] = y * t[3];
|
||||
mat[4] = y * t[4];
|
||||
|
||||
// Translation
|
||||
mat[2] = -copysign(1.0f, mat[0] + mat[1]);
|
||||
mat[5] = -copysign(1.0f, mat[3] + mat[4]);
|
||||
|
||||
// Identity
|
||||
mat[8] = 1.0f;
|
||||
}
|
||||
|
||||
int64_t getPPIDof(int64_t pid) {
|
||||
#if defined(KERN_PROC_PID)
|
||||
int mib[] = {
|
||||
|
@ -785,13 +764,13 @@ std::vector<SCallstackFrameInfo> getBacktrace() {
|
|||
|
||||
#ifdef HAS_EXECINFO
|
||||
void* bt[1024];
|
||||
size_t btSize;
|
||||
int btSize;
|
||||
char** btSymbols;
|
||||
|
||||
btSize = backtrace(bt, 1024);
|
||||
btSymbols = backtrace_symbols(bt, btSize);
|
||||
|
||||
for (size_t i = 0; i < btSize; ++i) {
|
||||
for (auto i = 0; i < btSize; ++i) {
|
||||
callstack.emplace_back(SCallstackFrameInfo{bt[i], std::string{btSymbols[i]}});
|
||||
}
|
||||
#else
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
#include "math/Math.hpp"
|
||||
#include <vector>
|
||||
#include <format>
|
||||
#include "../SharedDefs.hpp"
|
||||
#include "../macros.hpp"
|
||||
|
||||
struct SCallstackFrameInfo {
|
||||
void* adr = nullptr;
|
||||
|
@ -13,7 +15,7 @@ struct SCallstackFrameInfo {
|
|||
};
|
||||
|
||||
struct SWorkspaceIDName {
|
||||
int id = -1;
|
||||
WORKSPACEID id = WORKSPACE_INVALID;
|
||||
std::string name;
|
||||
};
|
||||
|
||||
|
@ -32,7 +34,6 @@ int64_t getPPIDof(int64_t pid);
|
|||
int64_t configStringToInt(const std::string&);
|
||||
Vector2D configStringToVector2D(const std::string&);
|
||||
std::optional<float> getPlusMinusKeywordResult(std::string in, float relative);
|
||||
void matrixProjection(float mat[9], int w, int h, wl_output_transform tr);
|
||||
double normalizeAngleRad(double ang);
|
||||
std::vector<SCallstackFrameInfo> getBacktrace();
|
||||
void throwError(const std::string& err);
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "Monitor.hpp"
|
||||
#include "MiscFunctions.hpp"
|
||||
#include "math/Math.hpp"
|
||||
#include "sync/SyncReleaser.hpp"
|
||||
#include "../Compositor.hpp"
|
||||
#include "../config/ConfigValue.hpp"
|
||||
#include "../protocols/GammaControl.hpp"
|
||||
|
@ -8,13 +9,18 @@
|
|||
#include "../protocols/LayerShell.hpp"
|
||||
#include "../protocols/PresentationTime.hpp"
|
||||
#include "../protocols/DRMLease.hpp"
|
||||
#include "../protocols/DRMSyncobj.hpp"
|
||||
#include "../protocols/core/Output.hpp"
|
||||
#include "../managers/PointerManager.hpp"
|
||||
#include "../managers/eventLoop/EventLoopManager.hpp"
|
||||
#include "../protocols/core/Compositor.hpp"
|
||||
#include "sync/SyncTimeline.hpp"
|
||||
#include <aquamarine/output/Output.hpp>
|
||||
#include "debug/Log.hpp"
|
||||
#include <hyprutils/string/String.hpp>
|
||||
#include <hyprutils/utils/ScopeGuard.hpp>
|
||||
using namespace Hyprutils::String;
|
||||
using namespace Hyprutils::Utils;
|
||||
|
||||
int ratHandler(void* data) {
|
||||
g_pHyprRenderer->renderMonitor((CMonitor*)data);
|
||||
|
@ -22,7 +28,7 @@ int ratHandler(void* data) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
CMonitor::CMonitor() : state(this) {
|
||||
CMonitor::CMonitor(SP<Aquamarine::IOutput> output_) : state(this), output(output_) {
|
||||
;
|
||||
}
|
||||
|
||||
|
@ -31,6 +37,7 @@ CMonitor::~CMonitor() {
|
|||
}
|
||||
|
||||
void CMonitor::onConnect(bool noRule) {
|
||||
CScopeGuard x = {[]() { g_pCompositor->arrangeMonitors(); }};
|
||||
|
||||
if (output->supportsExplicit) {
|
||||
inTimeline = CSyncTimeline::create(output->getBackend()->drmFD());
|
||||
|
@ -38,13 +45,26 @@ void CMonitor::onConnect(bool noRule) {
|
|||
}
|
||||
|
||||
listeners.frame = output->events.frame.registerListener([this](std::any d) { Events::listener_monitorFrame(this, nullptr); });
|
||||
listeners.destroy = output->events.destroy.registerListener([this](std::any d) { Events::listener_monitorDestroy(this, nullptr); });
|
||||
listeners.commit = output->events.commit.registerListener([this](std::any d) { Events::listener_monitorCommit(this, nullptr); });
|
||||
listeners.needsFrame =
|
||||
output->events.needsFrame.registerListener([this](std::any d) { g_pCompositor->scheduleFrameForMonitor(this, Aquamarine::IOutput::AQ_SCHEDULE_NEEDS_FRAME); });
|
||||
|
||||
listeners.presented = output->events.present.registerListener([this](std::any d) {
|
||||
auto E = std::any_cast<Aquamarine::IOutput::SPresentEvent>(d);
|
||||
PROTO::presentation->onPresented(this, E.when, E.refresh, E.seq, E.flags);
|
||||
PROTO::presentation->onPresented(self.lock(), E.when, E.refresh, E.seq, E.flags);
|
||||
});
|
||||
|
||||
listeners.destroy = output->events.destroy.registerListener([this](std::any d) {
|
||||
Debug::log(LOG, "Destroy called for monitor {}", szName);
|
||||
|
||||
onDisconnect(true);
|
||||
|
||||
output = nullptr;
|
||||
m_bRenderingInitPassed = false;
|
||||
|
||||
Debug::log(LOG, "Removing monitor {} from realMonitors", szName);
|
||||
|
||||
std::erase_if(g_pCompositor->m_vRealMonitors, [&](SP<CMonitor>& el) { return el.get() == this; });
|
||||
});
|
||||
|
||||
listeners.state = output->events.state.registerListener([this](std::any d) {
|
||||
|
@ -77,6 +97,7 @@ void CMonitor::onConnect(bool noRule) {
|
|||
tearingState.canTear = output->getBackend()->type() == Aquamarine::AQ_BACKEND_DRM;
|
||||
|
||||
if (m_bEnabled) {
|
||||
output->state->resetExplicitFences();
|
||||
output->state->setEnabled(true);
|
||||
state.commit();
|
||||
return;
|
||||
|
@ -96,11 +117,12 @@ void CMonitor::onConnect(bool noRule) {
|
|||
createdByUser = true; // should be true. WL and Headless backends should be addable / removable
|
||||
|
||||
// get monitor rule that matches
|
||||
SMonitorRule monitorRule = g_pConfigManager->getMonitorRuleFor(*this);
|
||||
SMonitorRule monitorRule = g_pConfigManager->getMonitorRuleFor(self.lock());
|
||||
|
||||
// if it's disabled, disable and ignore
|
||||
if (monitorRule.disabled) {
|
||||
|
||||
output->state->resetExplicitFences();
|
||||
output->state->setEnabled(false);
|
||||
|
||||
if (!state.commit())
|
||||
|
@ -137,6 +159,7 @@ void CMonitor::onConnect(bool noRule) {
|
|||
|
||||
m_bEnabled = true;
|
||||
|
||||
output->state->resetExplicitFences();
|
||||
output->state->setEnabled(true);
|
||||
|
||||
// set mode, also applies
|
||||
|
@ -152,7 +175,7 @@ void CMonitor::onConnect(bool noRule) {
|
|||
|
||||
setupDefaultWS(monitorRule);
|
||||
|
||||
for (auto& ws : g_pCompositor->m_vWorkspaces) {
|
||||
for (auto const& ws : g_pCompositor->m_vWorkspaces) {
|
||||
if (!valid(ws))
|
||||
continue;
|
||||
|
||||
|
@ -173,10 +196,6 @@ void CMonitor::onConnect(bool noRule) {
|
|||
if (!activeMonitorRule.mirrorOf.empty())
|
||||
setMirror(activeMonitorRule.mirrorOf);
|
||||
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"monitoradded", szName});
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"monitoraddedv2", std::format("{},{},{}", ID, szName, szShortDescription)});
|
||||
EMIT_HOOK_EVENT("monitorAdded", this);
|
||||
|
||||
if (!g_pCompositor->m_pLastMonitor) // set the last monitor if it isnt set yet
|
||||
g_pCompositor->setActiveMonitor(this);
|
||||
|
||||
|
@ -188,7 +207,7 @@ void CMonitor::onConnect(bool noRule) {
|
|||
|
||||
// verify last mon valid
|
||||
bool found = false;
|
||||
for (auto& m : g_pCompositor->m_vMonitors) {
|
||||
for (auto const& m : g_pCompositor->m_vMonitors) {
|
||||
if (m == g_pCompositor->m_pLastMonitor) {
|
||||
found = true;
|
||||
break;
|
||||
|
@ -205,9 +224,20 @@ void CMonitor::onConnect(bool noRule) {
|
|||
PROTO::gamma->applyGammaToState(this);
|
||||
|
||||
events.connect.emit();
|
||||
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"monitoradded", szName});
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"monitoraddedv2", std::format("{},{},{}", ID, szName, szShortDescription)});
|
||||
EMIT_HOOK_EVENT("monitorAdded", this);
|
||||
}
|
||||
|
||||
void CMonitor::onDisconnect(bool destroy) {
|
||||
CScopeGuard x = {[this]() {
|
||||
if (g_pCompositor->m_bIsShuttingDown)
|
||||
return;
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"monitorremoved", szName});
|
||||
EMIT_HOOK_EVENT("monitorRemoved", this);
|
||||
g_pCompositor->arrangeMonitors();
|
||||
}};
|
||||
|
||||
if (renderTimer) {
|
||||
wl_event_source_remove(renderTimer);
|
||||
|
@ -223,7 +253,7 @@ void CMonitor::onDisconnect(bool destroy) {
|
|||
|
||||
// Cleanup everything. Move windows back, snap cursor, shit.
|
||||
CMonitor* BACKUPMON = nullptr;
|
||||
for (auto& m : g_pCompositor->m_vMonitors) {
|
||||
for (auto const& m : g_pCompositor->m_vMonitors) {
|
||||
if (m.get() != this) {
|
||||
BACKUPMON = m.get();
|
||||
break;
|
||||
|
@ -240,7 +270,7 @@ void CMonitor::onDisconnect(bool destroy) {
|
|||
}
|
||||
|
||||
if (!mirrors.empty()) {
|
||||
for (auto& m : mirrors) {
|
||||
for (auto const& m : mirrors) {
|
||||
m->setMirror("");
|
||||
}
|
||||
|
||||
|
@ -253,7 +283,7 @@ void CMonitor::onDisconnect(bool destroy) {
|
|||
listeners.commit.reset();
|
||||
|
||||
for (size_t i = 0; i < 4; ++i) {
|
||||
for (auto& ls : m_aLayerSurfaceLayers[i]) {
|
||||
for (auto const& ls : m_aLayerSurfaceLayers[i]) {
|
||||
if (ls->layerSurface && !ls->fadingOut)
|
||||
ls->layerSurface->sendClosed();
|
||||
}
|
||||
|
@ -262,9 +292,6 @@ void CMonitor::onDisconnect(bool destroy) {
|
|||
|
||||
Debug::log(LOG, "Removed monitor {}!", szName);
|
||||
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"monitorremoved", szName});
|
||||
EMIT_HOOK_EVENT("monitorRemoved", this);
|
||||
|
||||
if (!BACKUPMON) {
|
||||
Debug::log(WARN, "Unplugged last monitor, entering an unsafe state. Good luck my friend.");
|
||||
g_pCompositor->enterUnsafeState();
|
||||
|
@ -279,13 +306,13 @@ void CMonitor::onDisconnect(bool destroy) {
|
|||
|
||||
// move workspaces
|
||||
std::deque<PHLWORKSPACE> wspToMove;
|
||||
for (auto& w : g_pCompositor->m_vWorkspaces) {
|
||||
for (auto const& w : g_pCompositor->m_vWorkspaces) {
|
||||
if (w->m_iMonitorID == ID || !g_pCompositor->getMonitorFromID(w->m_iMonitorID)) {
|
||||
wspToMove.push_back(w);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& w : wspToMove) {
|
||||
for (auto const& w : wspToMove) {
|
||||
w->m_szLastMonitor = szName;
|
||||
g_pCompositor->moveWorkspaceToMonitor(w, BACKUPMON);
|
||||
w->startAnim(true, true, true);
|
||||
|
@ -300,6 +327,7 @@ void CMonitor::onDisconnect(bool destroy) {
|
|||
activeWorkspace->m_bVisible = false;
|
||||
activeWorkspace.reset();
|
||||
|
||||
output->state->resetExplicitFences();
|
||||
output->state->setEnabled(false);
|
||||
|
||||
if (!state.commit())
|
||||
|
@ -312,7 +340,7 @@ void CMonitor::onDisconnect(bool destroy) {
|
|||
int mostHz = 0;
|
||||
CMonitor* pMonitorMostHz = nullptr;
|
||||
|
||||
for (auto& m : g_pCompositor->m_vMonitors) {
|
||||
for (auto const& m : g_pCompositor->m_vMonitors) {
|
||||
if (m->refreshRate > mostHz && m.get() != this) {
|
||||
pMonitorMostHz = m.get();
|
||||
mostHz = m->refreshRate;
|
||||
|
@ -357,7 +385,7 @@ bool CMonitor::shouldSkipScheduleFrameOnMouseEvent() {
|
|||
*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 / *PMINRR) {
|
||||
if (shouldSkip && *PMINRR && lastPresentationTimer.getMillis() > 1000.0f / *PMINRR) {
|
||||
// damage whole screen because some previous cursor box damages were skipped
|
||||
damage.damageEntire();
|
||||
return false;
|
||||
|
@ -382,8 +410,8 @@ bool CMonitor::matchesStaticSelector(const std::string& selector) const {
|
|||
}
|
||||
}
|
||||
|
||||
int CMonitor::findAvailableDefaultWS() {
|
||||
for (size_t i = 1; i < INT32_MAX; ++i) {
|
||||
WORKSPACEID CMonitor::findAvailableDefaultWS() {
|
||||
for (WORKSPACEID i = 1; i < LONG_MAX; ++i) {
|
||||
if (g_pCompositor->getWorkspaceByID(i))
|
||||
continue;
|
||||
|
||||
|
@ -393,7 +421,7 @@ int CMonitor::findAvailableDefaultWS() {
|
|||
return i;
|
||||
}
|
||||
|
||||
return INT32_MAX; // shouldn't be reachable
|
||||
return LONG_MAX; // shouldn't be reachable
|
||||
}
|
||||
|
||||
void CMonitor::setupDefaultWS(const SMonitorRule& monitorRule) {
|
||||
|
@ -468,7 +496,7 @@ void CMonitor::setMirror(const std::string& mirrorOf) {
|
|||
pMirrorOf = nullptr;
|
||||
|
||||
// set rule
|
||||
const auto RULE = g_pConfigManager->getMonitorRuleFor(*this);
|
||||
const auto RULE = g_pConfigManager->getMonitorRuleFor(self.lock());
|
||||
|
||||
vecPosition = RULE.offset;
|
||||
|
||||
|
@ -496,7 +524,7 @@ void CMonitor::setMirror(const std::string& mirrorOf) {
|
|||
g_pHyprRenderer->applyMonitorRule(this, (SMonitorRule*)&RULE, true); // will apply the offset and stuff
|
||||
} else {
|
||||
CMonitor* BACKUPMON = nullptr;
|
||||
for (auto& m : g_pCompositor->m_vMonitors) {
|
||||
for (auto const& m : g_pCompositor->m_vMonitors) {
|
||||
if (m.get() != this) {
|
||||
BACKUPMON = m.get();
|
||||
break;
|
||||
|
@ -505,13 +533,13 @@ void CMonitor::setMirror(const std::string& mirrorOf) {
|
|||
|
||||
// move all the WS
|
||||
std::deque<PHLWORKSPACE> wspToMove;
|
||||
for (auto& w : g_pCompositor->m_vWorkspaces) {
|
||||
for (auto const& w : g_pCompositor->m_vWorkspaces) {
|
||||
if (w->m_iMonitorID == ID) {
|
||||
wspToMove.push_back(w);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& w : wspToMove) {
|
||||
for (auto const& w : wspToMove) {
|
||||
g_pCompositor->moveWorkspaceToMonitor(w, BACKUPMON);
|
||||
w->startAnim(true, true, true);
|
||||
}
|
||||
|
@ -585,7 +613,7 @@ void CMonitor::changeWorkspace(const PHLWORKSPACE& pWorkspace, bool internal, bo
|
|||
pWorkspace->startAnim(true, ANIMTOLEFT);
|
||||
|
||||
// move pinned windows
|
||||
for (auto& w : g_pCompositor->m_vWindows) {
|
||||
for (auto const& w : g_pCompositor->m_vWindows) {
|
||||
if (w->m_pWorkspace == POLDWORKSPACE && w->m_bPinned)
|
||||
w->moveToWorkspace(pWorkspace);
|
||||
}
|
||||
|
@ -631,7 +659,7 @@ void CMonitor::changeWorkspace(const PHLWORKSPACE& pWorkspace, bool internal, bo
|
|||
g_pCompositor->updateFullscreenFadeOnWorkspace(activeSpecialWorkspace);
|
||||
}
|
||||
|
||||
void CMonitor::changeWorkspace(const int& id, bool internal, bool noMouseMove, bool noFocus) {
|
||||
void CMonitor::changeWorkspace(const WORKSPACEID& id, bool internal, bool noMouseMove, bool noFocus) {
|
||||
changeWorkspace(g_pCompositor->getWorkspaceByID(id), internal, noMouseMove, noFocus);
|
||||
}
|
||||
|
||||
|
@ -694,14 +722,14 @@ void CMonitor::setSpecialWorkspace(const PHLWORKSPACE& pWorkspace) {
|
|||
if (animate)
|
||||
pWorkspace->startAnim(true, true);
|
||||
|
||||
for (auto& w : g_pCompositor->m_vWindows) {
|
||||
for (auto const& w : g_pCompositor->m_vWindows) {
|
||||
if (w->m_pWorkspace == pWorkspace) {
|
||||
w->m_iMonitorID = ID;
|
||||
w->updateSurfaceScaleTransformDetails();
|
||||
w->setAnimationsToMove();
|
||||
|
||||
const auto MIDDLE = w->middle();
|
||||
if (w->m_bIsFloating && !VECINRECT(MIDDLE, vecPosition.x, vecPosition.y, vecPosition.x + vecSize.x, vecPosition.y + vecSize.y) && w->m_iX11Type != 2) {
|
||||
if (w->m_bIsFloating && !VECINRECT(MIDDLE, vecPosition.x, vecPosition.y, vecPosition.x + vecSize.x, vecPosition.y + vecSize.y) && !w->isX11OverrideRedirect()) {
|
||||
// if it's floating and the middle isnt on the current mon, move it to the center
|
||||
const auto PMONFROMMIDDLE = g_pCompositor->getMonitorFromVector(MIDDLE);
|
||||
Vector2D pos = w->m_vRealPosition.goal();
|
||||
|
@ -738,7 +766,7 @@ void CMonitor::setSpecialWorkspace(const PHLWORKSPACE& pWorkspace) {
|
|||
g_pCompositor->updateSuspendedStates();
|
||||
}
|
||||
|
||||
void CMonitor::setSpecialWorkspace(const int& id) {
|
||||
void CMonitor::setSpecialWorkspace(const WORKSPACEID& id) {
|
||||
setSpecialWorkspace(g_pCompositor->getWorkspaceByID(id));
|
||||
}
|
||||
|
||||
|
@ -751,19 +779,16 @@ Vector2D CMonitor::middle() {
|
|||
}
|
||||
|
||||
void CMonitor::updateMatrix() {
|
||||
matrixIdentity(projMatrix.data());
|
||||
if (transform != WL_OUTPUT_TRANSFORM_NORMAL) {
|
||||
matrixTranslate(projMatrix.data(), vecPixelSize.x / 2.0, vecPixelSize.y / 2.0);
|
||||
matrixTransform(projMatrix.data(), wlTransformToHyprutils(transform));
|
||||
matrixTranslate(projMatrix.data(), -vecTransformedSize.x / 2.0, -vecTransformedSize.y / 2.0);
|
||||
}
|
||||
projMatrix = Mat3x3::identity();
|
||||
if (transform != WL_OUTPUT_TRANSFORM_NORMAL)
|
||||
projMatrix.translate(vecPixelSize / 2.0).transform(wlTransformToHyprutils(transform)).translate(-vecTransformedSize / 2.0);
|
||||
}
|
||||
|
||||
int64_t CMonitor::activeWorkspaceID() {
|
||||
WORKSPACEID CMonitor::activeWorkspaceID() {
|
||||
return activeWorkspace ? activeWorkspace->m_iID : 0;
|
||||
}
|
||||
|
||||
int64_t CMonitor::activeSpecialWorkspaceID() {
|
||||
WORKSPACEID CMonitor::activeSpecialWorkspaceID() {
|
||||
return activeSpecialWorkspace ? activeSpecialWorkspace->m_iID : 0;
|
||||
}
|
||||
|
||||
|
@ -771,20 +796,28 @@ CBox CMonitor::logicalBox() {
|
|||
return {vecPosition, vecSize};
|
||||
}
|
||||
|
||||
static void onDoneSource(void* data) {
|
||||
auto pMonitor = (CMonitor*)data;
|
||||
|
||||
if (!PROTO::outputs.contains(pMonitor->szName))
|
||||
void CMonitor::scheduleDone() {
|
||||
if (doneScheduled)
|
||||
return;
|
||||
|
||||
PROTO::outputs.at(pMonitor->szName)->sendDone();
|
||||
doneScheduled = true;
|
||||
|
||||
g_pEventLoopManager->doLater([M = self] {
|
||||
if (!M) // if M is gone, we got destroyed, doesn't matter.
|
||||
return;
|
||||
|
||||
if (!PROTO::outputs.contains(M->szName))
|
||||
return;
|
||||
|
||||
PROTO::outputs.at(M->szName)->sendDone();
|
||||
M->doneScheduled = false;
|
||||
});
|
||||
}
|
||||
|
||||
void CMonitor::scheduleDone() {
|
||||
if (doneSource)
|
||||
return;
|
||||
|
||||
doneSource = wl_event_loop_add_idle(g_pCompositor->m_sWLEventLoop, ::onDoneSource, this);
|
||||
void CMonitor::setCTM(const Mat3x3& ctm_) {
|
||||
ctm = ctm_;
|
||||
ctmUpdated = true;
|
||||
g_pCompositor->scheduleFrameForMonitor(this, Aquamarine::IOutput::scheduleFrameReason::AQ_SCHEDULE_NEEDS_FRAME);
|
||||
}
|
||||
|
||||
bool CMonitor::attemptDirectScanout() {
|
||||
|
@ -808,28 +841,92 @@ bool CMonitor::attemptDirectScanout() {
|
|||
if (!PSURFACE->current.buffer || !PSURFACE->current.texture || !PSURFACE->current.texture->m_pEglImage /* dmabuf */)
|
||||
return false;
|
||||
|
||||
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;
|
||||
|
||||
if (drmFormat != params.format) {
|
||||
output->state->setFormat(params.format);
|
||||
drmFormat = params.format;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
if (!state.test())
|
||||
if (!state.test()) {
|
||||
Debug::log(TRACE, "attemptDirectScanout: failed basic test");
|
||||
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);
|
||||
Debug::log(TRACE, "presentFeedback for DS");
|
||||
PSURFACE->presentFeedback(&now, this, true);
|
||||
PSURFACE->presentFeedback(&now, self.lock());
|
||||
|
||||
output->state->addDamage(CBox{{}, vecPixelSize});
|
||||
output->state->resetExplicitFences();
|
||||
|
||||
if (state.commit()) {
|
||||
if (DOEXPLICIT) {
|
||||
Debug::log(TRACE, "attemptDirectScanout: setting IN_FENCE for aq to {}", explicitWaitFD);
|
||||
output->state->setExplicitInFence(explicitWaitFD);
|
||||
}
|
||||
|
||||
bool ok = output->commit();
|
||||
|
||||
if (!ok && DOEXPLICIT) {
|
||||
Debug::log(TRACE, "attemptDirectScanout: EXPLICIT SYNC FAILED: commit() returned false. Resetting fences and retrying, might result in glitches.");
|
||||
output->state->resetExplicitFences();
|
||||
|
||||
ok = output->commit();
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -837,6 +934,11 @@ bool CMonitor::attemptDirectScanout() {
|
|||
return true;
|
||||
}
|
||||
|
||||
void CMonitor::debugLastPresentation(const std::string& message) {
|
||||
Debug::log(TRACE, "{} (last presentation {} - {} fps)", message, lastPresentationTimer.getMillis(),
|
||||
lastPresentationTimer.getMillis() > 0 ? 1000.0f / lastPresentationTimer.getMillis() : 0.0f);
|
||||
}
|
||||
|
||||
CMonitorState::CMonitorState(CMonitor* owner) {
|
||||
m_pOwner = owner;
|
||||
}
|
||||
|
@ -846,17 +948,20 @@ CMonitorState::~CMonitorState() {
|
|||
}
|
||||
|
||||
void CMonitorState::ensureBufferPresent() {
|
||||
if (!m_pOwner->output->state->state().enabled) {
|
||||
const auto STATE = m_pOwner->output->state->state();
|
||||
if (!STATE.enabled) {
|
||||
Debug::log(TRACE, "CMonitorState::ensureBufferPresent: Ignoring, monitor is not enabled");
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_pOwner->output->state->state().buffer)
|
||||
if (STATE.buffer) {
|
||||
if (const auto params = STATE.buffer->dmabuf(); params.success && params.format == m_pOwner->drmFormat)
|
||||
return;
|
||||
}
|
||||
|
||||
// this is required for modesetting being possible and might be missing in case of first tests in the renderer
|
||||
// where we test modes and buffers
|
||||
Debug::log(LOG, "CMonitorState::ensureBufferPresent: no buffer, attaching one from the swapchain for modeset being possible");
|
||||
Debug::log(LOG, "CMonitorState::ensureBufferPresent: no buffer or mismatched format, attaching one from the swapchain for modeset being possible");
|
||||
m_pOwner->output->state->setBuffer(m_pOwner->output->swapchain->next(nullptr));
|
||||
m_pOwner->output->swapchain->rollback(); // restore the counter, don't advance the swapchain
|
||||
}
|
||||
|
@ -890,7 +995,7 @@ bool CMonitorState::updateSwapchain() {
|
|||
Debug::log(WARN, "updateSwapchain: No mode?");
|
||||
return true;
|
||||
}
|
||||
options.format = STATE.drmFormat;
|
||||
options.format = m_pOwner->drmFormat;
|
||||
options.scanout = true;
|
||||
options.length = 2;
|
||||
options.size = MODE->pixelSize;
|
||||
|
|
|
@ -59,7 +59,7 @@ class CMonitorState {
|
|||
|
||||
class CMonitor {
|
||||
public:
|
||||
CMonitor();
|
||||
CMonitor(SP<Aquamarine::IOutput> output);
|
||||
~CMonitor();
|
||||
|
||||
Vector2D vecPosition = Vector2D(-1, -1); // means unset
|
||||
|
@ -70,7 +70,7 @@ class CMonitor {
|
|||
|
||||
bool primary = false;
|
||||
|
||||
uint64_t ID = -1;
|
||||
MONITORID ID = MONITOR_INVALID;
|
||||
PHLWORKSPACE activeWorkspace = nullptr;
|
||||
PHLWORKSPACE activeSpecialWorkspace = nullptr;
|
||||
float setScale = 1; // scale set by cfg
|
||||
|
@ -96,10 +96,12 @@ class CMonitor {
|
|||
bool scheduledRecalc = false;
|
||||
wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
||||
float xwaylandScale = 1.f;
|
||||
std::array<float, 9> projMatrix = {0};
|
||||
Mat3x3 projMatrix;
|
||||
std::optional<Vector2D> forceSize;
|
||||
SP<Aquamarine::SOutputMode> currentMode;
|
||||
SP<Aquamarine::CSwapchain> cursorSwapchain;
|
||||
uint32_t drmFormat = DRM_FORMAT_INVALID;
|
||||
uint32_t prevDrmFormat = DRM_FORMAT_INVALID;
|
||||
|
||||
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.
|
||||
|
@ -121,7 +123,6 @@ class CMonitor {
|
|||
// explicit sync
|
||||
SP<CSyncTimeline> inTimeline;
|
||||
SP<CSyncTimeline> outTimeline;
|
||||
uint64_t lastWaitPoint = 0;
|
||||
uint64_t commitSeq = 0;
|
||||
|
||||
WP<CMonitor> self;
|
||||
|
@ -130,6 +131,10 @@ class CMonitor {
|
|||
CMonitor* pMirrorOf = nullptr;
|
||||
std::vector<CMonitor*> mirrors;
|
||||
|
||||
// ctm
|
||||
Mat3x3 ctm = Mat3x3::identity();
|
||||
bool ctmUpdated = false;
|
||||
|
||||
// for tearing
|
||||
PHLWINDOWREF solitaryClient;
|
||||
|
||||
|
@ -167,17 +172,20 @@ class CMonitor {
|
|||
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 int& id, 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 int& id);
|
||||
void setSpecialWorkspace(const WORKSPACEID& id);
|
||||
void moveTo(const Vector2D& pos);
|
||||
Vector2D middle();
|
||||
void updateMatrix();
|
||||
int64_t activeWorkspaceID();
|
||||
int64_t activeSpecialWorkspaceID();
|
||||
WORKSPACEID activeWorkspaceID();
|
||||
WORKSPACEID activeSpecialWorkspaceID();
|
||||
CBox logicalBox();
|
||||
void scheduleDone();
|
||||
bool attemptDirectScanout();
|
||||
void setCTM(const Mat3x3& ctm);
|
||||
|
||||
void debugLastPresentation(const std::string& message);
|
||||
|
||||
bool m_bEnabled = false;
|
||||
bool m_bRenderingInitPassed = false;
|
||||
|
@ -190,9 +198,9 @@ class CMonitor {
|
|||
|
||||
private:
|
||||
void setupDefaultWS(const SMonitorRule&);
|
||||
int findAvailableDefaultWS();
|
||||
WORKSPACEID findAvailableDefaultWS();
|
||||
|
||||
wl_event_source* doneSource = nullptr;
|
||||
bool doneScheduled = false;
|
||||
|
||||
struct {
|
||||
CHyprSignalListener frame;
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <cstring>
|
||||
|
||||
namespace Systemd {
|
||||
int SdBooted(void) {
|
||||
|
|