mirror of
https://github.com/hyprwm/hypridle.git
synced 2025-12-21 09:30:02 +01:00
Compare commits
No commits in common. "main" and "v0.1.4" have entirely different histories.
19 changed files with 248 additions and 715 deletions
101
.clang-tidy
101
.clang-tidy
|
|
@ -1,101 +0,0 @@
|
||||||
WarningsAsErrors: '*'
|
|
||||||
HeaderFilterRegex: '.*\.hpp'
|
|
||||||
FormatStyle: 'file'
|
|
||||||
Checks: >
|
|
||||||
-*,
|
|
||||||
bugprone-*,
|
|
||||||
-bugprone-easily-swappable-parameters,
|
|
||||||
-bugprone-forward-declaration-namespace,
|
|
||||||
-bugprone-forward-declaration-namespace,
|
|
||||||
-bugprone-macro-parentheses,
|
|
||||||
-bugprone-narrowing-conversions,
|
|
||||||
-bugprone-branch-clone,
|
|
||||||
-bugprone-assignment-in-if-condition,
|
|
||||||
concurrency-*,
|
|
||||||
-concurrency-mt-unsafe,
|
|
||||||
cppcoreguidelines-*,
|
|
||||||
-cppcoreguidelines-owning-memory,
|
|
||||||
-cppcoreguidelines-avoid-magic-numbers,
|
|
||||||
-cppcoreguidelines-pro-bounds-constant-array-index,
|
|
||||||
-cppcoreguidelines-avoid-const-or-ref-data-members,
|
|
||||||
-cppcoreguidelines-non-private-member-variables-in-classes,
|
|
||||||
-cppcoreguidelines-avoid-goto,
|
|
||||||
-cppcoreguidelines-pro-bounds-array-to-pointer-decay,
|
|
||||||
-cppcoreguidelines-avoid-do-while,
|
|
||||||
-cppcoreguidelines-avoid-non-const-global-variables,
|
|
||||||
-cppcoreguidelines-special-member-functions,
|
|
||||||
-cppcoreguidelines-explicit-virtual-functions,
|
|
||||||
-cppcoreguidelines-avoid-c-arrays,
|
|
||||||
-cppcoreguidelines-pro-bounds-pointer-arithmetic,
|
|
||||||
-cppcoreguidelines-narrowing-conversions,
|
|
||||||
-cppcoreguidelines-pro-type-union-access,
|
|
||||||
-cppcoreguidelines-pro-type-member-init,
|
|
||||||
-cppcoreguidelines-macro-usage,
|
|
||||||
-cppcoreguidelines-macro-to-enum,
|
|
||||||
-cppcoreguidelines-init-variables,
|
|
||||||
-cppcoreguidelines-pro-type-cstyle-cast,
|
|
||||||
-cppcoreguidelines-pro-type-vararg,
|
|
||||||
-cppcoreguidelines-pro-type-reinterpret-cast,
|
|
||||||
google-global-names-in-headers,
|
|
||||||
-google-readability-casting,
|
|
||||||
google-runtime-operator,
|
|
||||||
misc-*,
|
|
||||||
-misc-unused-parameters,
|
|
||||||
-misc-no-recursion,
|
|
||||||
-misc-non-private-member-variables-in-classes,
|
|
||||||
-misc-include-cleaner,
|
|
||||||
-misc-use-anonymous-namespace,
|
|
||||||
-misc-const-correctness,
|
|
||||||
modernize-*,
|
|
||||||
-modernize-return-braced-init-list,
|
|
||||||
-modernize-use-trailing-return-type,
|
|
||||||
-modernize-use-using,
|
|
||||||
-modernize-use-override,
|
|
||||||
-modernize-avoid-c-arrays,
|
|
||||||
-modernize-macro-to-enum,
|
|
||||||
-modernize-loop-convert,
|
|
||||||
-modernize-use-nodiscard,
|
|
||||||
-modernize-pass-by-value,
|
|
||||||
-modernize-use-auto,
|
|
||||||
performance-*,
|
|
||||||
-performance-avoid-endl,
|
|
||||||
-performance-unnecessary-value-param,
|
|
||||||
portability-std-allocator-const,
|
|
||||||
readability-*,
|
|
||||||
-readability-function-cognitive-complexity,
|
|
||||||
-readability-function-size,
|
|
||||||
-readability-identifier-length,
|
|
||||||
-readability-magic-numbers,
|
|
||||||
-readability-uppercase-literal-suffix,
|
|
||||||
-readability-braces-around-statements,
|
|
||||||
-readability-redundant-access-specifiers,
|
|
||||||
-readability-else-after-return,
|
|
||||||
-readability-container-data-pointer,
|
|
||||||
-readability-implicit-bool-conversion,
|
|
||||||
-readability-avoid-nested-conditional-operator,
|
|
||||||
-readability-redundant-member-init,
|
|
||||||
-readability-redundant-string-init,
|
|
||||||
-readability-avoid-const-params-in-decls,
|
|
||||||
-readability-named-parameter,
|
|
||||||
-readability-convert-member-functions-to-static,
|
|
||||||
-readability-qualified-auto,
|
|
||||||
-readability-make-member-function-const,
|
|
||||||
-readability-isolate-declaration,
|
|
||||||
-readability-inconsistent-declaration-parameter-name,
|
|
||||||
-clang-diagnostic-error,
|
|
||||||
|
|
||||||
CheckOptions:
|
|
||||||
performance-for-range-copy.WarnOnAllAutoCopies: true
|
|
||||||
performance-inefficient-string-concatenation.StrictMode: true
|
|
||||||
readability-braces-around-statements.ShortStatementLines: 0
|
|
||||||
readability-identifier-naming.ClassCase: CamelCase
|
|
||||||
readability-identifier-naming.ClassIgnoredRegexp: I.*
|
|
||||||
readability-identifier-naming.ClassPrefix: C # We can't use regex here?!?!?!?
|
|
||||||
readability-identifier-naming.EnumCase: CamelCase
|
|
||||||
readability-identifier-naming.EnumPrefix: e
|
|
||||||
readability-identifier-naming.EnumConstantCase: UPPER_CASE
|
|
||||||
readability-identifier-naming.FunctionCase: camelBack
|
|
||||||
readability-identifier-naming.NamespaceCase: CamelCase
|
|
||||||
readability-identifier-naming.NamespacePrefix: N
|
|
||||||
readability-identifier-naming.StructPrefix: S
|
|
||||||
readability-identifier-naming.StructCase: CamelCase
|
|
||||||
31
.github/workflows/nix.yml
vendored
31
.github/workflows/nix.yml
vendored
|
|
@ -7,35 +7,8 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Install Nix
|
- uses: DeterminateSystems/nix-installer-action@main
|
||||||
uses: nixbuild/nix-quick-install-action@v31
|
- uses: DeterminateSystems/magic-nix-cache-action@main
|
||||||
with:
|
|
||||||
nix_conf: |
|
|
||||||
keep-env-derivations = true
|
|
||||||
keep-outputs = true
|
|
||||||
|
|
||||||
- name: Restore and save Nix store
|
|
||||||
uses: nix-community/cache-nix-action@v6
|
|
||||||
with:
|
|
||||||
# restore and save a cache using this key
|
|
||||||
primary-key: nix-${{ runner.os }}-${{ hashFiles('**/*.nix', '**/flake.lock') }}
|
|
||||||
# if there's no cache hit, restore a cache by this prefix
|
|
||||||
restore-prefixes-first-match: nix-${{ runner.os }}-
|
|
||||||
# collect garbage until the Nix store size (in bytes) is at most this number
|
|
||||||
# before trying to save a new cache
|
|
||||||
# 1G = 1073741824
|
|
||||||
gc-max-store-size-linux: 1G
|
|
||||||
# do purge caches
|
|
||||||
purge: true
|
|
||||||
# purge all versions of the cache
|
|
||||||
purge-prefixes: nix-${{ runner.os }}-
|
|
||||||
# created more than this number of seconds ago
|
|
||||||
purge-created: 0
|
|
||||||
# or, last accessed more than this number of seconds ago
|
|
||||||
# relative to the start of the `Post Restore and save Nix store` phase
|
|
||||||
purge-last-accessed: 0
|
|
||||||
# except any version with the key that is the same as the `primary-key`
|
|
||||||
purge-primary-key: never
|
|
||||||
|
|
||||||
# not needed (yet)
|
# not needed (yet)
|
||||||
# - uses: cachix/cachix-action@v12
|
# - uses: cachix/cachix-action@v12
|
||||||
|
|
|
||||||
6
.gitignore
vendored
6
.gitignore
vendored
|
|
@ -1,7 +1,3 @@
|
||||||
.vscode/
|
.vscode/
|
||||||
build/
|
build/
|
||||||
protocols/
|
protocols/
|
||||||
.clangd/
|
|
||||||
.direnv/
|
|
||||||
.cache/
|
|
||||||
compile_commands.json
|
|
||||||
|
|
@ -18,17 +18,14 @@ else()
|
||||||
message(STATUS "Configuring hypridle in Release with CMake")
|
message(STATUS "Configuring hypridle in Release with CMake")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_compile_definitions(HYPRIDLE_VERSION="${VERSION}")
|
|
||||||
|
|
||||||
include_directories(. "protocols/")
|
include_directories(. "protocols/")
|
||||||
|
|
||||||
include(GNUInstallDirs)
|
include(GNUInstallDirs)
|
||||||
|
|
||||||
# configure
|
# configure
|
||||||
set(CMAKE_CXX_STANDARD 23)
|
set(CMAKE_CXX_STANDARD 23)
|
||||||
set(CMAKE_EXPORT_COMPILE_COMMANDS TRUE)
|
add_compile_options(-Wall -Wextra -Wno-unused-parameter -Wno-unused-value
|
||||||
add_compile_options(-Wall -Wextra -Wuseless-cast -Wno-unused-parameter
|
-Wno-missing-field-initializers -Wno-narrowing)
|
||||||
-Wno-unused-value -Wno-missing-field-initializers)
|
|
||||||
configure_file(systemd/hypridle.service.in systemd/hypridle.service @ONLY)
|
configure_file(systemd/hypridle.service.in systemd/hypridle.service @ONLY)
|
||||||
|
|
||||||
# dependencies
|
# dependencies
|
||||||
|
|
@ -36,14 +33,13 @@ message(STATUS "Checking deps...")
|
||||||
|
|
||||||
find_package(Threads REQUIRED)
|
find_package(Threads REQUIRED)
|
||||||
find_package(PkgConfig REQUIRED)
|
find_package(PkgConfig REQUIRED)
|
||||||
find_package(hyprwayland-scanner 0.4.4 REQUIRED)
|
|
||||||
pkg_check_modules(
|
pkg_check_modules(
|
||||||
deps
|
deps
|
||||||
REQUIRED
|
REQUIRED
|
||||||
IMPORTED_TARGET
|
IMPORTED_TARGET
|
||||||
wayland-client
|
wayland-client
|
||||||
wayland-protocols
|
wayland-protocols
|
||||||
hyprlang>=0.6.0
|
hyprlang>=0.4.0
|
||||||
hyprutils>=0.2.0
|
hyprutils>=0.2.0
|
||||||
sdbus-c++>=0.2.0)
|
sdbus-c++>=0.2.0)
|
||||||
|
|
||||||
|
|
@ -52,47 +48,45 @@ add_executable(hypridle ${SRCFILES})
|
||||||
target_link_libraries(hypridle PRIVATE rt Threads::Threads PkgConfig::deps)
|
target_link_libraries(hypridle PRIVATE rt Threads::Threads PkgConfig::deps)
|
||||||
|
|
||||||
# protocols
|
# protocols
|
||||||
pkg_get_variable(WAYLAND_PROTOCOLS_DIR wayland-protocols pkgdatadir)
|
find_program(WaylandScanner NAMES wayland-scanner)
|
||||||
|
message(STATUS "Found WaylandScanner at ${WaylandScanner}")
|
||||||
|
execute_process(
|
||||||
|
COMMAND pkg-config --variable=pkgdatadir wayland-protocols
|
||||||
|
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||||
|
OUTPUT_VARIABLE WAYLAND_PROTOCOLS_DIR
|
||||||
|
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||||
message(STATUS "Found wayland-protocols at ${WAYLAND_PROTOCOLS_DIR}")
|
message(STATUS "Found wayland-protocols at ${WAYLAND_PROTOCOLS_DIR}")
|
||||||
pkg_get_variable(WAYLAND_SCANNER_PKGDATA_DIR wayland-scanner pkgdatadir)
|
|
||||||
message(STATUS "Found wayland-scanner pkgdatadir at ${WAYLAND_SCANNER_PKGDATA_DIR}")
|
|
||||||
|
|
||||||
pkg_check_modules(hyprland_protocols_dep REQUIRED IMPORTED_TARGET hyprland-protocols>=0.6.0)
|
function(protocol protoPath protoName external)
|
||||||
pkg_get_variable(HYPRLAND_PROTOCOLS hyprland-protocols pkgdatadir)
|
|
||||||
message(STATUS "Found hyprland-protocols at ${HYPRLAND_PROTOCOLS}")
|
|
||||||
|
|
||||||
function(protocolnew protoPath protoName external)
|
|
||||||
if(external)
|
if(external)
|
||||||
set(path ${protoPath})
|
execute_process(
|
||||||
|
COMMAND ${WaylandScanner} client-header ${protoPath}
|
||||||
|
protocols/${protoName}-protocol.h
|
||||||
|
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
|
||||||
|
execute_process(
|
||||||
|
COMMAND ${WaylandScanner} private-code ${protoPath}
|
||||||
|
protocols/${protoName}-protocol.c
|
||||||
|
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
|
||||||
|
target_sources(hypridle PRIVATE protocols/${protoName}-protocol.c)
|
||||||
else()
|
else()
|
||||||
set(path ${WAYLAND_PROTOCOLS_DIR}/${protoPath})
|
execute_process(
|
||||||
|
COMMAND
|
||||||
|
${WaylandScanner} client-header ${WAYLAND_PROTOCOLS_DIR}/${protoPath}
|
||||||
|
protocols/${protoName}-protocol.h
|
||||||
|
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
|
||||||
|
execute_process(
|
||||||
|
COMMAND
|
||||||
|
${WaylandScanner} private-code ${WAYLAND_PROTOCOLS_DIR}/${protoPath}
|
||||||
|
protocols/${protoName}-protocol.c
|
||||||
|
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
|
||||||
|
target_sources(hypridle PRIVATE protocols/${protoName}-protocol.c)
|
||||||
endif()
|
endif()
|
||||||
message(STATUS "Full proto path: ${path}")
|
|
||||||
add_custom_command(
|
|
||||||
OUTPUT ${CMAKE_SOURCE_DIR}/protocols/${protoName}.cpp
|
|
||||||
${CMAKE_SOURCE_DIR}/protocols/${protoName}.hpp
|
|
||||||
COMMAND hyprwayland-scanner --client ${path}/${protoName}.xml
|
|
||||||
${CMAKE_SOURCE_DIR}/protocols/
|
|
||||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
|
|
||||||
target_sources(hypridle PRIVATE protocols/${protoName}.cpp
|
|
||||||
protocols/${protoName}.hpp)
|
|
||||||
endfunction()
|
|
||||||
function(protocolWayland)
|
|
||||||
add_custom_command(
|
|
||||||
OUTPUT ${CMAKE_SOURCE_DIR}/protocols/wayland.cpp
|
|
||||||
${CMAKE_SOURCE_DIR}/protocols/wayland.hpp
|
|
||||||
COMMAND hyprwayland-scanner --wayland-enums --client
|
|
||||||
${WAYLAND_SCANNER_PKGDATA_DIR}/wayland.xml ${CMAKE_SOURCE_DIR}/protocols/
|
|
||||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
|
|
||||||
target_sources(hypridle PRIVATE protocols/wayland.cpp protocols/wayland.hpp)
|
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
make_directory(${CMAKE_SOURCE_DIR}/protocols) # we don't ship any custom ones so
|
make_directory(${CMAKE_SOURCE_DIR}/protocols) # we don't ship any custom ones so
|
||||||
|
# the dir won't be there
|
||||||
protocolwayland()
|
protocol("staging/ext-idle-notify/ext-idle-notify-v1.xml" "ext-idle-notify-v1"
|
||||||
|
false)
|
||||||
protocolnew("staging/ext-idle-notify" "ext-idle-notify-v1" false)
|
|
||||||
protocolnew("${HYPRLAND_PROTOCOLS}/protocols" "hyprland-lock-notify-v1" true)
|
|
||||||
|
|
||||||
# Installation
|
# Installation
|
||||||
install(TARGETS hypridle)
|
install(TARGETS hypridle)
|
||||||
|
|
|
||||||
|
|
@ -34,17 +34,15 @@ will make those events ignored.
|
||||||
## Dependencies
|
## Dependencies
|
||||||
- wayland
|
- wayland
|
||||||
- wayland-protocols
|
- wayland-protocols
|
||||||
- hyprland-protocols
|
|
||||||
- hyprlang >= 0.4.0
|
- hyprlang >= 0.4.0
|
||||||
- sdbus-c++
|
- sdbus-c++
|
||||||
- hyprwayland-scanner
|
|
||||||
|
|
||||||
## Building & Installation
|
## Building & Installation
|
||||||
|
|
||||||
### Building:
|
### Building:
|
||||||
```sh
|
```sh
|
||||||
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:PATH=/usr -S . -B ./build
|
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -S . -B ./build
|
||||||
cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
|
cmake --build ./build --config Release --target hypridle -j`nproc 2>/dev/null || getconf _NPROCESSORS_CONF`
|
||||||
```
|
```
|
||||||
|
|
||||||
### Installation:
|
### Installation:
|
||||||
|
|
|
||||||
2
VERSION
2
VERSION
|
|
@ -1 +1 @@
|
||||||
0.1.7
|
0.1.4
|
||||||
|
|
|
||||||
|
|
@ -2,36 +2,16 @@
|
||||||
# for more configuration options, refer https://wiki.hyprland.org/Hypr-Ecosystem/hypridle
|
# for more configuration options, refer https://wiki.hyprland.org/Hypr-Ecosystem/hypridle
|
||||||
|
|
||||||
general {
|
general {
|
||||||
lock_cmd = pidof hyprlock || hyprlock # avoid starting multiple hyprlock instances.
|
lock_cmd = notify-send "lock!" # dbus/sysd lock command (loginctl lock-session)
|
||||||
before_sleep_cmd = loginctl lock-session # lock before suspend.
|
unlock_cmd = notify-send "unlock!" # same as above, but unlock
|
||||||
after_sleep_cmd = hyprctl dispatch dpms on # to avoid having to press a key twice to turn on the display.
|
before_sleep_cmd = notify-send "Zzz" # command ran before sleep
|
||||||
|
after_sleep_cmd = notify-send "Awake!" # command ran after sleep
|
||||||
|
ignore_dbus_inhibit = false # whether to ignore dbus-sent idle-inhibit requests (used by e.g. firefox or steam)
|
||||||
|
ignore_systemd_inhibit = false # whether to ignore systemd-inhibit --what=idle inhibitors
|
||||||
}
|
}
|
||||||
|
|
||||||
listener {
|
listener {
|
||||||
timeout = 150 # 2.5min.
|
timeout = 300 # in seconds
|
||||||
on-timeout = brightnessctl -s set 10 # set monitor backlight to minimum, avoid 0 on OLED monitor.
|
on-timeout = notify-send "You are idle!" # command to run when timeout has passed
|
||||||
on-resume = brightnessctl -r # monitor backlight restore.
|
on-resume = notify-send "Welcome back!" # command to run when activity is detected after timeout has fired.
|
||||||
}
|
|
||||||
|
|
||||||
# turn off keyboard backlight, comment out this section if you dont have a keyboard backlight.
|
|
||||||
listener {
|
|
||||||
timeout = 150 # 2.5min.
|
|
||||||
on-timeout = brightnessctl -sd rgb:kbd_backlight set 0 # turn off keyboard backlight.
|
|
||||||
on-resume = brightnessctl -rd rgb:kbd_backlight # turn on keyboard backlight.
|
|
||||||
}
|
|
||||||
|
|
||||||
listener {
|
|
||||||
timeout = 300 # 5min.
|
|
||||||
on-timeout = loginctl lock-session # lock screen when timeout has passed.
|
|
||||||
}
|
|
||||||
|
|
||||||
listener {
|
|
||||||
timeout = 330 # 5.5min.
|
|
||||||
on-timeout = hyprctl dispatch dpms off # screen off when timeout has passed.
|
|
||||||
on-resume = hyprctl dispatch dpms on # screen on when activity is detected after timeout has fired.
|
|
||||||
}
|
|
||||||
|
|
||||||
listener {
|
|
||||||
timeout = 1800 # 30min.
|
|
||||||
on-timeout = systemctl suspend # suspend pc.
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
66
flake.lock
generated
66
flake.lock
generated
|
|
@ -1,28 +1,5 @@
|
||||||
{
|
{
|
||||||
"nodes": {
|
"nodes": {
|
||||||
"hyprland-protocols": {
|
|
||||||
"inputs": {
|
|
||||||
"nixpkgs": [
|
|
||||||
"nixpkgs"
|
|
||||||
],
|
|
||||||
"systems": [
|
|
||||||
"systems"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1765214753,
|
|
||||||
"narHash": "sha256-P9zdGXOzToJJgu5sVjv7oeOGPIIwrd9hAUAP3PsmBBs=",
|
|
||||||
"owner": "hyprwm",
|
|
||||||
"repo": "hyprland-protocols",
|
|
||||||
"rev": "3f3860b869014c00e8b9e0528c7b4ddc335c21ab",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "hyprwm",
|
|
||||||
"repo": "hyprland-protocols",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"hyprlang": {
|
"hyprlang": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"hyprutils": [
|
"hyprutils": [
|
||||||
|
|
@ -36,11 +13,11 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1764612430,
|
"lastModified": 1721324361,
|
||||||
"narHash": "sha256-54ltTSbI6W+qYGMchAgCR6QnC1kOdKXN6X6pJhOWxFg=",
|
"narHash": "sha256-BiJKO0IIdnSwHQBSrEJlKlFr753urkLE48wtt0UhNG4=",
|
||||||
"owner": "hyprwm",
|
"owner": "hyprwm",
|
||||||
"repo": "hyprlang",
|
"repo": "hyprlang",
|
||||||
"rev": "0d00dc118981531aa731150b6ea551ef037acddd",
|
"rev": "adbefbf49664a6c2c8bf36b6487fd31e3eb68086",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
@ -59,11 +36,11 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1766160771,
|
"lastModified": 1721324102,
|
||||||
"narHash": "sha256-roINUGikWRqqgKrD4iotKbGj3ZKJl3hjMz5l/SyKrHw=",
|
"narHash": "sha256-WAZ0X6yJW1hFG6otkHBfyJDKRpNP5stsRqdEuHrFRpk=",
|
||||||
"owner": "hyprwm",
|
"owner": "hyprwm",
|
||||||
"repo": "hyprutils",
|
"repo": "hyprutils",
|
||||||
"rev": "5ac060bfcf2f12b3a6381156ebbc13826a05b09f",
|
"rev": "962582a090bc233c4de9d9897f46794280288989",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
@ -72,36 +49,13 @@
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"hyprwayland-scanner": {
|
|
||||||
"inputs": {
|
|
||||||
"nixpkgs": [
|
|
||||||
"nixpkgs"
|
|
||||||
],
|
|
||||||
"systems": [
|
|
||||||
"systems"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1763640274,
|
|
||||||
"narHash": "sha256-Uan1Nl9i4TF/kyFoHnTq1bd/rsWh4GAK/9/jDqLbY5A=",
|
|
||||||
"owner": "hyprwm",
|
|
||||||
"repo": "hyprwayland-scanner",
|
|
||||||
"rev": "f6cf414ca0e16a4d30198fd670ec86df3c89f671",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "hyprwm",
|
|
||||||
"repo": "hyprwayland-scanner",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1766070988,
|
"lastModified": 1721138476,
|
||||||
"narHash": "sha256-G/WVghka6c4bAzMhTwT2vjLccg/awmHkdKSd2JrycLc=",
|
"narHash": "sha256-+W5eZOhhemLQxelojLxETfbFbc19NWawsXBlapYpqIA=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "c6245e83d836d0433170a16eb185cefe0572f8b8",
|
"rev": "ad0b5eed1b6031efaed382844806550c3dcb4206",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
@ -113,10 +67,8 @@
|
||||||
},
|
},
|
||||||
"root": {
|
"root": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"hyprland-protocols": "hyprland-protocols",
|
|
||||||
"hyprlang": "hyprlang",
|
"hyprlang": "hyprlang",
|
||||||
"hyprutils": "hyprutils",
|
"hyprutils": "hyprutils",
|
||||||
"hyprwayland-scanner": "hyprwayland-scanner",
|
|
||||||
"nixpkgs": "nixpkgs",
|
"nixpkgs": "nixpkgs",
|
||||||
"systems": "systems"
|
"systems": "systems"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
12
flake.nix
12
flake.nix
|
|
@ -17,18 +17,6 @@
|
||||||
inputs.nixpkgs.follows = "nixpkgs";
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
inputs.systems.follows = "systems";
|
inputs.systems.follows = "systems";
|
||||||
};
|
};
|
||||||
|
|
||||||
hyprland-protocols = {
|
|
||||||
url = "github:hyprwm/hyprland-protocols";
|
|
||||||
inputs.nixpkgs.follows = "nixpkgs";
|
|
||||||
inputs.systems.follows = "systems";
|
|
||||||
};
|
|
||||||
|
|
||||||
hyprwayland-scanner = {
|
|
||||||
url = "github:hyprwm/hyprwayland-scanner";
|
|
||||||
inputs.nixpkgs.follows = "nixpkgs";
|
|
||||||
inputs.systems.follows = "systems";
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
outputs = {
|
outputs = {
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,11 @@
|
||||||
{
|
{
|
||||||
|
lib,
|
||||||
|
stdenv,
|
||||||
cmake,
|
cmake,
|
||||||
hyprland-protocols,
|
pkg-config,
|
||||||
hyprlang,
|
hyprlang,
|
||||||
hyprutils,
|
hyprutils,
|
||||||
hyprwayland-scanner,
|
sdbus-cpp,
|
||||||
lib,
|
|
||||||
pkg-config,
|
|
||||||
sdbus-cpp_2,
|
|
||||||
stdenv,
|
|
||||||
systemd,
|
systemd,
|
||||||
wayland,
|
wayland,
|
||||||
wayland-protocols,
|
wayland-protocols,
|
||||||
|
|
@ -21,16 +19,14 @@ stdenv.mkDerivation {
|
||||||
|
|
||||||
nativeBuildInputs = [
|
nativeBuildInputs = [
|
||||||
cmake
|
cmake
|
||||||
hyprwayland-scanner
|
|
||||||
pkg-config
|
pkg-config
|
||||||
wayland-scanner
|
wayland-scanner
|
||||||
];
|
];
|
||||||
|
|
||||||
buildInputs = [
|
buildInputs = [
|
||||||
hyprland-protocols
|
|
||||||
hyprlang
|
hyprlang
|
||||||
hyprutils
|
hyprutils
|
||||||
sdbus-cpp_2
|
sdbus-cpp
|
||||||
systemd
|
systemd
|
||||||
wayland
|
wayland
|
||||||
wayland-protocols
|
wayland-protocols
|
||||||
|
|
|
||||||
|
|
@ -13,16 +13,28 @@ in {
|
||||||
default = inputs.self.overlays.hypridle;
|
default = inputs.self.overlays.hypridle;
|
||||||
|
|
||||||
hypridle = lib.composeManyExtensions [
|
hypridle = lib.composeManyExtensions [
|
||||||
inputs.hyprland-protocols.overlays.default
|
|
||||||
inputs.hyprlang.overlays.default
|
inputs.hyprlang.overlays.default
|
||||||
inputs.hyprutils.overlays.default
|
inputs.hyprutils.overlays.default
|
||||||
inputs.hyprwayland-scanner.overlays.default
|
inputs.self.overlays.sdbuscpp
|
||||||
(final: prev: {
|
(final: prev: {
|
||||||
hypridle = prev.callPackage ./default.nix {
|
hypridle = prev.callPackage ./default.nix {
|
||||||
stdenv = prev.gcc15Stdenv;
|
stdenv = prev.gcc13Stdenv;
|
||||||
version = version + "+date=" + (mkDate (inputs.self.lastModifiedDate or "19700101")) + "_" + (inputs.self.shortRev or "dirty");
|
version = version + "+date=" + (mkDate (inputs.self.lastModifiedDate or "19700101")) + "_" + (inputs.self.shortRev or "dirty");
|
||||||
inherit (final) hyprlang;
|
inherit (final) hyprlang;
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
];
|
];
|
||||||
|
|
||||||
|
sdbuscpp = final: prev: {
|
||||||
|
sdbus-cpp = prev.sdbus-cpp.overrideAttrs (self: super: {
|
||||||
|
version = "2.0.0";
|
||||||
|
|
||||||
|
src = final.fetchFromGitHub {
|
||||||
|
owner = "Kistler-group";
|
||||||
|
repo = "sdbus-cpp";
|
||||||
|
rev = "refs/tags/v${self.version}";
|
||||||
|
hash = "sha256-W8V5FRhV3jtERMFrZ4gf30OpIQLYoj2yYGpnYOmH2+g=";
|
||||||
|
};
|
||||||
|
});
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,6 @@
|
||||||
#include "ConfigManager.hpp"
|
#include "ConfigManager.hpp"
|
||||||
#include "../helpers/Log.hpp"
|
|
||||||
#include "../helpers/MiscFunctions.hpp"
|
|
||||||
#include <hyprutils/path/Path.hpp>
|
#include <hyprutils/path/Path.hpp>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <glob.h>
|
|
||||||
#include <cstring>
|
|
||||||
|
|
||||||
static std::string getMainConfigPath() {
|
static std::string getMainConfigPath() {
|
||||||
static const auto paths = Hyprutils::Path::findConfig("hypridle");
|
static const auto paths = Hyprutils::Path::findConfig("hypridle");
|
||||||
|
|
@ -17,20 +13,6 @@ static std::string getMainConfigPath() {
|
||||||
CConfigManager::CConfigManager(std::string configPath) :
|
CConfigManager::CConfigManager(std::string configPath) :
|
||||||
m_config(configPath.empty() ? getMainConfigPath().c_str() : configPath.c_str(), Hyprlang::SConfigOptions{.throwAllErrors = true, .allowMissingConfig = false}) {
|
m_config(configPath.empty() ? getMainConfigPath().c_str() : configPath.c_str(), Hyprlang::SConfigOptions{.throwAllErrors = true, .allowMissingConfig = false}) {
|
||||||
;
|
;
|
||||||
configCurrentPath = configPath.empty() ? getMainConfigPath() : configPath;
|
|
||||||
configHeadPath = configCurrentPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
static Hyprlang::CParseResult handleSource(const char* c, const char* v) {
|
|
||||||
const std::string VALUE = v;
|
|
||||||
const std::string COMMAND = c;
|
|
||||||
|
|
||||||
const auto RESULT = g_pConfigManager->handleSource(COMMAND, VALUE);
|
|
||||||
|
|
||||||
Hyprlang::CParseResult result;
|
|
||||||
if (RESULT.has_value())
|
|
||||||
result.setError(RESULT.value().c_str());
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CConfigManager::init() {
|
void CConfigManager::init() {
|
||||||
|
|
@ -38,23 +20,13 @@ void CConfigManager::init() {
|
||||||
m_config.addSpecialConfigValue("listener", "timeout", Hyprlang::INT{-1});
|
m_config.addSpecialConfigValue("listener", "timeout", Hyprlang::INT{-1});
|
||||||
m_config.addSpecialConfigValue("listener", "on-timeout", Hyprlang::STRING{""});
|
m_config.addSpecialConfigValue("listener", "on-timeout", Hyprlang::STRING{""});
|
||||||
m_config.addSpecialConfigValue("listener", "on-resume", Hyprlang::STRING{""});
|
m_config.addSpecialConfigValue("listener", "on-resume", Hyprlang::STRING{""});
|
||||||
m_config.addSpecialConfigValue("listener", "ignore_inhibit", Hyprlang::INT{0});
|
|
||||||
|
|
||||||
m_config.addConfigValue("general:lock_cmd", Hyprlang::STRING{""});
|
m_config.addConfigValue("general:lock_cmd", Hyprlang::STRING{""});
|
||||||
m_config.addConfigValue("general:unlock_cmd", Hyprlang::STRING{""});
|
m_config.addConfigValue("general:unlock_cmd", Hyprlang::STRING{""});
|
||||||
m_config.addConfigValue("general:on_lock_cmd", Hyprlang::STRING{""});
|
|
||||||
m_config.addConfigValue("general:on_unlock_cmd", Hyprlang::STRING{""});
|
|
||||||
m_config.addConfigValue("general:before_sleep_cmd", Hyprlang::STRING{""});
|
m_config.addConfigValue("general:before_sleep_cmd", Hyprlang::STRING{""});
|
||||||
m_config.addConfigValue("general:after_sleep_cmd", Hyprlang::STRING{""});
|
m_config.addConfigValue("general:after_sleep_cmd", Hyprlang::STRING{""});
|
||||||
m_config.addConfigValue("general:ignore_dbus_inhibit", Hyprlang::INT{0});
|
m_config.addConfigValue("general:ignore_dbus_inhibit", Hyprlang::INT{0});
|
||||||
m_config.addConfigValue("general:ignore_systemd_inhibit", Hyprlang::INT{0});
|
m_config.addConfigValue("general:ignore_systemd_inhibit", Hyprlang::INT{0});
|
||||||
m_config.addConfigValue("general:ignore_wayland_inhibit", Hyprlang::INT{0});
|
|
||||||
m_config.addConfigValue("general:inhibit_sleep", Hyprlang::INT{2});
|
|
||||||
|
|
||||||
// track the file in the circular dependency chain
|
|
||||||
alreadyIncludedSourceFiles.insert(std::filesystem::canonical(configHeadPath));
|
|
||||||
|
|
||||||
m_config.registerHandler(&::handleSource, "source", {.allowFlags = false});
|
|
||||||
|
|
||||||
m_config.commence();
|
m_config.commence();
|
||||||
|
|
||||||
|
|
@ -87,8 +59,6 @@ Hyprlang::CParseResult CConfigManager::postParse() {
|
||||||
rule.onTimeout = std::any_cast<Hyprlang::STRING>(m_config.getSpecialConfigValue("listener", "on-timeout", k.c_str()));
|
rule.onTimeout = std::any_cast<Hyprlang::STRING>(m_config.getSpecialConfigValue("listener", "on-timeout", k.c_str()));
|
||||||
rule.onResume = std::any_cast<Hyprlang::STRING>(m_config.getSpecialConfigValue("listener", "on-resume", k.c_str()));
|
rule.onResume = std::any_cast<Hyprlang::STRING>(m_config.getSpecialConfigValue("listener", "on-resume", k.c_str()));
|
||||||
|
|
||||||
rule.ignoreInhibit = std::any_cast<Hyprlang::INT>(m_config.getSpecialConfigValue("listener", "ignore_inhibit", k.c_str()));
|
|
||||||
|
|
||||||
if (timeout == -1) {
|
if (timeout == -1) {
|
||||||
result.setError("Category has a missing timeout setting");
|
result.setError("Category has a missing timeout setting");
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -98,8 +68,7 @@ Hyprlang::CParseResult CConfigManager::postParse() {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto& r : m_vRules) {
|
for (auto& r : m_vRules) {
|
||||||
Debug::log(LOG, "Registered timeout rule for {}s:\n on-timeout: {}\n on-resume: {}\n ignore_inhibit: {}", r.timeout, r.onTimeout, r.onResume,
|
Debug::log(LOG, "Registered timeout rule for {}s:\n on-timeout: {}\n on-resume: {}", r.timeout, r.onTimeout, r.onResume);
|
||||||
r.ignoreInhibit);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|
@ -109,55 +78,10 @@ std::vector<CConfigManager::STimeoutRule> CConfigManager::getRules() {
|
||||||
return m_vRules;
|
return m_vRules;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<std::string> CConfigManager::handleSource(const std::string& command, const std::string& rawpath) {
|
std::string CConfigManager::getOnTimeoutCommand() {
|
||||||
if (rawpath.length() < 2) {
|
return m_vRules.front().onTimeout;
|
||||||
return "source path " + rawpath + " bogus!";
|
}
|
||||||
}
|
|
||||||
std::unique_ptr<glob_t, void (*)(glob_t*)> glob_buf{new glob_t, [](glob_t* g) { globfree(g); }};
|
void* const* CConfigManager::getValuePtr(const std::string& name) {
|
||||||
memset(glob_buf.get(), 0, sizeof(glob_t));
|
return m_config.getConfigValuePtr(name.c_str())->getDataStaticPtr();
|
||||||
|
|
||||||
const auto CURRENTDIR = std::filesystem::path(configCurrentPath).parent_path().string();
|
|
||||||
|
|
||||||
if (auto r = glob(absolutePath(rawpath, CURRENTDIR).c_str(), GLOB_TILDE, nullptr, glob_buf.get()); r != 0) {
|
|
||||||
std::string err = std::format("source= globbing error: {}", r == GLOB_NOMATCH ? "found no match" : GLOB_ABORTED ? "read error" : "out of memory");
|
|
||||||
Debug::log(ERR, "{}", err);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = 0; i < glob_buf->gl_pathc; i++) {
|
|
||||||
const auto PATH = absolutePath(glob_buf->gl_pathv[i], CURRENTDIR);
|
|
||||||
|
|
||||||
if (PATH.empty() || PATH == configCurrentPath) {
|
|
||||||
Debug::log(WARN, "source= skipping invalid path");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (std::find(alreadyIncludedSourceFiles.begin(), alreadyIncludedSourceFiles.end(), PATH) != alreadyIncludedSourceFiles.end()) {
|
|
||||||
Debug::log(WARN, "source= skipping already included source file {} to prevent circular dependency", PATH);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!std::filesystem::is_regular_file(PATH)) {
|
|
||||||
if (std::filesystem::exists(PATH)) {
|
|
||||||
Debug::log(WARN, "source= skipping non-file {}", PATH);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
Debug::log(ERR, "source= file doesnt exist");
|
|
||||||
return "source file " + PATH + " doesn't exist!";
|
|
||||||
}
|
|
||||||
|
|
||||||
// track the file in the circular dependency chain
|
|
||||||
alreadyIncludedSourceFiles.insert(PATH);
|
|
||||||
|
|
||||||
// allow for nested config parsing
|
|
||||||
auto backupConfigPath = configCurrentPath;
|
|
||||||
configCurrentPath = PATH;
|
|
||||||
|
|
||||||
m_config.parseFile(PATH.c_str());
|
|
||||||
|
|
||||||
configCurrentPath = backupConfigPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
return {};
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@
|
||||||
|
|
||||||
#include <hyprlang.hpp>
|
#include <hyprlang.hpp>
|
||||||
|
|
||||||
#include <set>
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
|
|
@ -14,21 +13,14 @@ class CConfigManager {
|
||||||
void init();
|
void init();
|
||||||
|
|
||||||
struct STimeoutRule {
|
struct STimeoutRule {
|
||||||
uint64_t timeout = 0;
|
uint64_t timeout = 0;
|
||||||
std::string onTimeout = "";
|
std::string onTimeout = "";
|
||||||
std::string onResume = "";
|
std::string onResume = "";
|
||||||
bool ignoreInhibit = false;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
std::vector<STimeoutRule> getRules();
|
std::string getOnTimeoutCommand();
|
||||||
std::optional<std::string> handleSource(const std::string&, const std::string&);
|
std::vector<STimeoutRule> getRules();
|
||||||
std::string configCurrentPath, configHeadPath;
|
void* const* getValuePtr(const std::string& name);
|
||||||
std::set<std::string> alreadyIncludedSourceFiles;
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
Hyprlang::CSimpleConfigValue<T> getValue(const std::string& name) {
|
|
||||||
return Hyprlang::CSimpleConfigValue<T>(&m_config, name.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Hyprlang::CConfig m_config;
|
Hyprlang::CConfig m_config;
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,14 @@
|
||||||
|
|
||||||
#include "Hypridle.hpp"
|
#include "Hypridle.hpp"
|
||||||
#include "../helpers/Log.hpp"
|
#include "../helpers/Log.hpp"
|
||||||
#include "../config/ConfigManager.hpp"
|
#include "../config/ConfigManager.hpp"
|
||||||
#include "csignal"
|
#include "signal.h"
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <sys/poll.h>
|
#include <sys/poll.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <algorithm>
|
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <hyprutils/os/Process.hpp>
|
|
||||||
|
|
||||||
CHypridle::CHypridle() {
|
CHypridle::CHypridle() {
|
||||||
m_sWaylandState.display = wl_display_connect(nullptr);
|
m_sWaylandState.display = wl_display_connect(nullptr);
|
||||||
|
|
@ -21,32 +18,36 @@ CHypridle::CHypridle() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void handleGlobal(void* data, struct wl_registry* registry, uint32_t name, const char* interface, uint32_t version) {
|
||||||
|
g_pHypridle->onGlobal(data, registry, name, interface, version);
|
||||||
|
}
|
||||||
|
|
||||||
|
void handleGlobalRemove(void* data, struct wl_registry* registry, uint32_t name) {
|
||||||
|
g_pHypridle->onGlobalRemoved(data, registry, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const wl_registry_listener registryListener = {
|
||||||
|
.global = handleGlobal,
|
||||||
|
.global_remove = handleGlobalRemove,
|
||||||
|
};
|
||||||
|
|
||||||
|
void handleIdled(void* data, ext_idle_notification_v1* ext_idle_notification_v1) {
|
||||||
|
g_pHypridle->onIdled((CHypridle::SIdleListener*)data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void handleResumed(void* data, ext_idle_notification_v1* ext_idle_notification_v1) {
|
||||||
|
g_pHypridle->onResumed((CHypridle::SIdleListener*)data);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const ext_idle_notification_v1_listener idleListener = {
|
||||||
|
.idled = handleIdled,
|
||||||
|
.resumed = handleResumed,
|
||||||
|
};
|
||||||
|
|
||||||
void CHypridle::run() {
|
void CHypridle::run() {
|
||||||
m_sWaylandState.registry = makeShared<CCWlRegistry>((wl_proxy*)wl_display_get_registry(m_sWaylandState.display));
|
m_sWaylandState.registry = wl_display_get_registry(m_sWaylandState.display);
|
||||||
m_sWaylandState.registry->setGlobal([this](CCWlRegistry* r, uint32_t name, const char* interface, uint32_t version) {
|
|
||||||
const std::string IFACE = interface;
|
|
||||||
Debug::log(LOG, " | got iface: {} v{}", IFACE, version);
|
|
||||||
|
|
||||||
if (IFACE == ext_idle_notifier_v1_interface.name) {
|
wl_registry_add_listener(m_sWaylandState.registry, ®istryListener, nullptr);
|
||||||
m_sWaylandIdleState.notifier =
|
|
||||||
makeShared<CCExtIdleNotifierV1>((wl_proxy*)wl_registry_bind((wl_registry*)r->resource(), name, &ext_idle_notifier_v1_interface, version));
|
|
||||||
Debug::log(LOG, " > Bound to {} v{}", IFACE, version);
|
|
||||||
} else if (IFACE == hyprland_lock_notifier_v1_interface.name) {
|
|
||||||
m_sWaylandState.lockNotifier =
|
|
||||||
makeShared<CCHyprlandLockNotifierV1>((wl_proxy*)wl_registry_bind((wl_registry*)r->resource(), name, &hyprland_lock_notifier_v1_interface, version));
|
|
||||||
Debug::log(LOG, " > Bound to {} v{}", IFACE, version);
|
|
||||||
} else if (IFACE == wl_seat_interface.name) {
|
|
||||||
if (m_sWaylandState.seat) {
|
|
||||||
Debug::log(WARN, "Hypridle does not support multi-seat configurations. Only binding to the first seat.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_sWaylandState.seat = makeShared<CCWlSeat>((wl_proxy*)wl_registry_bind((wl_registry*)r->resource(), name, &wl_seat_interface, version));
|
|
||||||
Debug::log(LOG, " > Bound to {} v{}", IFACE, version);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
m_sWaylandState.registry->setGlobalRemove([](CCWlRegistry* r, uint32_t name) { Debug::log(LOG, " | removed iface {}", name); });
|
|
||||||
|
|
||||||
wl_display_roundtrip(m_sWaylandState.display);
|
wl_display_roundtrip(m_sWaylandState.display);
|
||||||
|
|
||||||
|
|
@ -55,41 +56,23 @@ void CHypridle::run() {
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const auto IGNOREWAYLANDINHIBIT = g_pConfigManager->getValue<Hyprlang::INT>("general:ignore_wayland_inhibit");
|
const auto RULES = g_pConfigManager->getRules();
|
||||||
|
|
||||||
const auto RULES = g_pConfigManager->getRules();
|
|
||||||
m_sWaylandIdleState.listeners.resize(RULES.size());
|
m_sWaylandIdleState.listeners.resize(RULES.size());
|
||||||
|
|
||||||
Debug::log(LOG, "found {} rules", RULES.size());
|
Debug::log(LOG, "found {} rules", RULES.size());
|
||||||
|
|
||||||
for (size_t i = 0; i < RULES.size(); ++i) {
|
for (size_t i = 0; i < RULES.size(); ++i) {
|
||||||
auto& l = m_sWaylandIdleState.listeners[i];
|
auto& l = m_sWaylandIdleState.listeners[i];
|
||||||
const auto& r = RULES[i];
|
const auto& r = RULES[i];
|
||||||
l.onRestore = r.onResume;
|
l.notification = ext_idle_notifier_v1_get_idle_notification(m_sWaylandIdleState.notifier, r.timeout * 1000 /* ms */, m_sWaylandState.seat);
|
||||||
l.onTimeout = r.onTimeout;
|
l.onRestore = r.onResume;
|
||||||
l.ignoreInhibit = r.ignoreInhibit;
|
l.onTimeout = r.onTimeout;
|
||||||
|
|
||||||
if (*IGNOREWAYLANDINHIBIT || r.ignoreInhibit)
|
ext_idle_notification_v1_add_listener(l.notification, &idleListener, &l);
|
||||||
l.notification =
|
|
||||||
makeShared<CCExtIdleNotificationV1>(m_sWaylandIdleState.notifier->sendGetInputIdleNotification(r.timeout * 1000 /* ms */, m_sWaylandState.seat->resource()));
|
|
||||||
else
|
|
||||||
l.notification =
|
|
||||||
makeShared<CCExtIdleNotificationV1>(m_sWaylandIdleState.notifier->sendGetIdleNotification(r.timeout * 1000 /* ms */, m_sWaylandState.seat->resource()));
|
|
||||||
|
|
||||||
l.notification->setData(&m_sWaylandIdleState.listeners[i]);
|
|
||||||
|
|
||||||
l.notification->setIdled([this](CCExtIdleNotificationV1* n) { onIdled((CHypridle::SIdleListener*)n->data()); });
|
|
||||||
l.notification->setResumed([this](CCExtIdleNotificationV1* n) { onResumed((CHypridle::SIdleListener*)n->data()); });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
wl_display_roundtrip(m_sWaylandState.display);
|
wl_display_roundtrip(m_sWaylandState.display);
|
||||||
|
|
||||||
if (m_sWaylandState.lockNotifier) {
|
|
||||||
m_sWaylandState.lockNotification = makeShared<CCHyprlandLockNotificationV1>(m_sWaylandState.lockNotifier->sendGetLockNotification());
|
|
||||||
m_sWaylandState.lockNotification->setLocked([this](CCHyprlandLockNotificationV1* n) { onLocked(); });
|
|
||||||
m_sWaylandState.lockNotification->setUnlocked([this](CCHyprlandLockNotificationV1* n) { onUnlocked(); });
|
|
||||||
}
|
|
||||||
|
|
||||||
Debug::log(LOG, "wayland done, registering dbus");
|
Debug::log(LOG, "wayland done, registering dbus");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
@ -99,46 +82,7 @@ void CHypridle::run() {
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_sWaylandState.lockNotifier)
|
|
||||||
Debug::log(WARN,
|
|
||||||
"Compositor is missing hyprland-lock-notify-v1!\n"
|
|
||||||
"general:inhibit_sleep=3, general:on_lock_cmd and general:on_unlock_cmd will not work.");
|
|
||||||
|
|
||||||
static const auto INHIBIT = g_pConfigManager->getValue<Hyprlang::INT>("general:inhibit_sleep");
|
|
||||||
static const auto SLEEPCMD = g_pConfigManager->getValue<Hyprlang::STRING>("general:before_sleep_cmd");
|
|
||||||
static const auto LOCKCMD = g_pConfigManager->getValue<Hyprlang::STRING>("general:lock_cmd");
|
|
||||||
|
|
||||||
switch (*INHIBIT) {
|
|
||||||
case 0: // disabled
|
|
||||||
m_inhibitSleepBehavior = SLEEP_INHIBIT_NONE;
|
|
||||||
break;
|
|
||||||
case 1: // enabled
|
|
||||||
m_inhibitSleepBehavior = SLEEP_INHIBIT_NORMAL;
|
|
||||||
break;
|
|
||||||
case 2: { // auto (enable, but wait until locked if before_sleep_cmd contains hyprlock, or loginctl lock-session and lock_cmd contains hyprlock.)
|
|
||||||
if (m_sWaylandState.lockNotifier && std::string{*SLEEPCMD}.contains("hyprlock"))
|
|
||||||
m_inhibitSleepBehavior = SLEEP_INHIBIT_LOCK_NOTIFY;
|
|
||||||
else if (m_sWaylandState.lockNotifier && std::string{*LOCKCMD}.contains("hyprlock") && std::string{*SLEEPCMD}.contains("lock-session"))
|
|
||||||
m_inhibitSleepBehavior = SLEEP_INHIBIT_LOCK_NOTIFY;
|
|
||||||
else
|
|
||||||
m_inhibitSleepBehavior = SLEEP_INHIBIT_NORMAL;
|
|
||||||
} break;
|
|
||||||
case 3: // wait until locked
|
|
||||||
if (m_sWaylandState.lockNotifier)
|
|
||||||
m_inhibitSleepBehavior = SLEEP_INHIBIT_LOCK_NOTIFY;
|
|
||||||
break;
|
|
||||||
default: Debug::log(ERR, "Invalid inhibit_sleep value: {}", *INHIBIT); break;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (m_inhibitSleepBehavior) {
|
|
||||||
case SLEEP_INHIBIT_NONE: Debug::log(LOG, "Sleep inhibition disabled"); break;
|
|
||||||
case SLEEP_INHIBIT_NORMAL: Debug::log(LOG, "Sleep inhibition enabled"); break;
|
|
||||||
case SLEEP_INHIBIT_LOCK_NOTIFY: Debug::log(LOG, "Sleep inhibition enabled - inhibiting until the wayland session gets locked"); break;
|
|
||||||
}
|
|
||||||
|
|
||||||
setupDBUS();
|
setupDBUS();
|
||||||
if (m_inhibitSleepBehavior != SLEEP_INHIBIT_NONE)
|
|
||||||
inhibitSleep();
|
|
||||||
enterEventLoop();
|
enterEventLoop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -195,7 +139,7 @@ void CHypridle::enterEventLoop() {
|
||||||
m_sEventLoopInternals.loopRequestMutex.unlock(); // unlock, we are ready to take events
|
m_sEventLoopInternals.loopRequestMutex.unlock(); // unlock, we are ready to take events
|
||||||
|
|
||||||
std::unique_lock lk(m_sEventLoopInternals.loopMutex);
|
std::unique_lock lk(m_sEventLoopInternals.loopMutex);
|
||||||
if (!m_sEventLoopInternals.shouldProcess) // avoid a lock if a thread managed to request something already since we .unlock()ed
|
if (m_sEventLoopInternals.shouldProcess == false) // avoid a lock if a thread managed to request something already since we .unlock()ed
|
||||||
m_sEventLoopInternals.loopSignal.wait(lk, [this] { return m_sEventLoopInternals.shouldProcess == true; }); // wait for events
|
m_sEventLoopInternals.loopSignal.wait(lk, [this] { return m_sEventLoopInternals.shouldProcess == true; }); // wait for events
|
||||||
|
|
||||||
m_sEventLoopInternals.loopRequestMutex.lock(); // lock incoming events
|
m_sEventLoopInternals.loopRequestMutex.lock(); // lock incoming events
|
||||||
|
|
@ -243,22 +187,84 @@ void CHypridle::enterEventLoop() {
|
||||||
Debug::log(ERR, "[core] Terminated");
|
Debug::log(ERR, "[core] Terminated");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CHypridle::onGlobal(void* data, struct wl_registry* registry, uint32_t name, const char* interface, uint32_t version) {
|
||||||
|
const std::string IFACE = interface;
|
||||||
|
Debug::log(LOG, " | got iface: {} v{}", IFACE, version);
|
||||||
|
|
||||||
|
if (IFACE == ext_idle_notifier_v1_interface.name) {
|
||||||
|
m_sWaylandIdleState.notifier = (ext_idle_notifier_v1*)wl_registry_bind(registry, name, &ext_idle_notifier_v1_interface, version);
|
||||||
|
Debug::log(LOG, " > Bound to {} v{}", IFACE, version);
|
||||||
|
} else if (IFACE == wl_seat_interface.name) {
|
||||||
|
if (m_sWaylandState.seat) {
|
||||||
|
Debug::log(WARN, "Hypridle does not support multi-seat configurations. Only binding to the first seat.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_sWaylandState.seat = (wl_seat*)wl_registry_bind(registry, name, &wl_seat_interface, version);
|
||||||
|
Debug::log(LOG, " > Bound to {} v{}", IFACE, version);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CHypridle::onGlobalRemoved(void* data, struct wl_registry* registry, uint32_t name) {
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
static void spawn(const std::string& args) {
|
static void spawn(const std::string& args) {
|
||||||
Debug::log(LOG, "Executing {}", args);
|
Debug::log(LOG, "Executing {}", args);
|
||||||
|
|
||||||
Hyprutils::OS::CProcess proc("/bin/sh", {"-c", args});
|
int socket[2];
|
||||||
if (!proc.runAsync()) {
|
if (pipe(socket) != 0) {
|
||||||
Debug::log(ERR, "Failed run \"{}\"", args);
|
Debug::log(LOG, "Unable to create pipe for fork");
|
||||||
|
}
|
||||||
|
|
||||||
|
pid_t child, grandchild;
|
||||||
|
child = fork();
|
||||||
|
if (child < 0) {
|
||||||
|
close(socket[0]);
|
||||||
|
close(socket[1]);
|
||||||
|
Debug::log(LOG, "Fail to create the first fork");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (child == 0) {
|
||||||
|
// run in child
|
||||||
|
|
||||||
|
sigset_t set;
|
||||||
|
sigemptyset(&set);
|
||||||
|
sigprocmask(SIG_SETMASK, &set, NULL);
|
||||||
|
|
||||||
|
grandchild = fork();
|
||||||
|
if (grandchild == 0) {
|
||||||
|
// run in grandchild
|
||||||
|
close(socket[0]);
|
||||||
|
close(socket[1]);
|
||||||
|
execl("/bin/sh", "/bin/sh", "-c", args.c_str(), nullptr);
|
||||||
|
// exit grandchild
|
||||||
|
_exit(0);
|
||||||
|
}
|
||||||
|
close(socket[0]);
|
||||||
|
write(socket[1], &grandchild, sizeof(grandchild));
|
||||||
|
close(socket[1]);
|
||||||
|
// exit child
|
||||||
|
_exit(0);
|
||||||
|
}
|
||||||
|
// run in parent
|
||||||
|
close(socket[1]);
|
||||||
|
read(socket[0], &grandchild, sizeof(grandchild));
|
||||||
|
close(socket[0]);
|
||||||
|
// clear child and leave grandchild to init
|
||||||
|
waitpid(child, NULL, 0);
|
||||||
|
if (grandchild < 0) {
|
||||||
|
Debug::log(LOG, "Failed to create the second fork");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug::log(LOG, "Process Created with pid {}", proc.pid());
|
Debug::log(LOG, "Process Created with pid {}", grandchild);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CHypridle::onIdled(SIdleListener* pListener) {
|
void CHypridle::onIdled(SIdleListener* pListener) {
|
||||||
Debug::log(LOG, "Idled: rule {:x}", (uintptr_t)pListener);
|
Debug::log(LOG, "Idled: rule {:x}", (uintptr_t)pListener);
|
||||||
isIdled = true;
|
isIdled = true;
|
||||||
if (g_pHypridle->m_iInhibitLocks > 0 && !pListener->ignoreInhibit) {
|
if (g_pHypridle->m_iInhibitLocks > 0) {
|
||||||
Debug::log(LOG, "Ignoring from onIdled(), inhibit locks: {}", g_pHypridle->m_iInhibitLocks);
|
Debug::log(LOG, "Ignoring from onIdled(), inhibit locks: {}", g_pHypridle->m_iInhibitLocks);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -275,7 +281,7 @@ void CHypridle::onIdled(SIdleListener* pListener) {
|
||||||
void CHypridle::onResumed(SIdleListener* pListener) {
|
void CHypridle::onResumed(SIdleListener* pListener) {
|
||||||
Debug::log(LOG, "Resumed: rule {:x}", (uintptr_t)pListener);
|
Debug::log(LOG, "Resumed: rule {:x}", (uintptr_t)pListener);
|
||||||
isIdled = false;
|
isIdled = false;
|
||||||
if (g_pHypridle->m_iInhibitLocks > 0 && !pListener->ignoreInhibit) {
|
if (g_pHypridle->m_iInhibitLocks > 0) {
|
||||||
Debug::log(LOG, "Ignoring from onResumed(), inhibit locks: {}", g_pHypridle->m_iInhibitLocks);
|
Debug::log(LOG, "Ignoring from onResumed(), inhibit locks: {}", g_pHypridle->m_iInhibitLocks);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -298,56 +304,23 @@ void CHypridle::onInhibit(bool lock) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_iInhibitLocks == 0 && isIdled) {
|
if (m_iInhibitLocks == 0 && isIdled) {
|
||||||
static const auto IGNOREWAYLANDINHIBIT = g_pConfigManager->getValue<Hyprlang::INT>("general:ignore_wayland_inhibit");
|
const auto RULES = g_pConfigManager->getRules();
|
||||||
|
|
||||||
const auto RULES = g_pConfigManager->getRules();
|
|
||||||
for (size_t i = 0; i < RULES.size(); ++i) {
|
for (size_t i = 0; i < RULES.size(); ++i) {
|
||||||
auto& l = m_sWaylandIdleState.listeners[i];
|
auto& l = m_sWaylandIdleState.listeners[i];
|
||||||
const auto& r = RULES[i];
|
const auto& r = RULES[i];
|
||||||
|
|
||||||
l.notification->sendDestroy();
|
ext_idle_notification_v1_destroy(l.notification);
|
||||||
|
|
||||||
if (*IGNOREWAYLANDINHIBIT || r.ignoreInhibit)
|
l.notification = ext_idle_notifier_v1_get_idle_notification(m_sWaylandIdleState.notifier, r.timeout * 1000 /* ms */, m_sWaylandState.seat);
|
||||||
l.notification =
|
|
||||||
makeShared<CCExtIdleNotificationV1>(m_sWaylandIdleState.notifier->sendGetInputIdleNotification(r.timeout * 1000 /* ms */, m_sWaylandState.seat->resource()));
|
|
||||||
else
|
|
||||||
l.notification =
|
|
||||||
makeShared<CCExtIdleNotificationV1>(m_sWaylandIdleState.notifier->sendGetIdleNotification(r.timeout * 1000 /* ms */, m_sWaylandState.seat->resource()));
|
|
||||||
|
|
||||||
l.notification->setData(&m_sWaylandIdleState.listeners[i]);
|
ext_idle_notification_v1_add_listener(l.notification, &idleListener, &l);
|
||||||
|
|
||||||
l.notification->setIdled([this](CCExtIdleNotificationV1* n) { onIdled((CHypridle::SIdleListener*)n->data()); });
|
|
||||||
l.notification->setResumed([this](CCExtIdleNotificationV1* n) { onResumed((CHypridle::SIdleListener*)n->data()); });
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug::log(LOG, "Inhibit locks: {}", m_iInhibitLocks);
|
Debug::log(LOG, "Inhibit locks: {}", m_iInhibitLocks);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CHypridle::onLocked() {
|
|
||||||
Debug::log(LOG, "Wayland session got locked");
|
|
||||||
m_isLocked = true;
|
|
||||||
|
|
||||||
static const auto LOCKCMD = g_pConfigManager->getValue<Hyprlang::STRING>("general:on_lock_cmd");
|
|
||||||
if (!std::string{*LOCKCMD}.empty())
|
|
||||||
spawn(*LOCKCMD);
|
|
||||||
|
|
||||||
if (m_inhibitSleepBehavior == SLEEP_INHIBIT_LOCK_NOTIFY)
|
|
||||||
uninhibitSleep();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CHypridle::onUnlocked() {
|
|
||||||
Debug::log(LOG, "Wayland session got unlocked");
|
|
||||||
m_isLocked = false;
|
|
||||||
|
|
||||||
if (m_inhibitSleepBehavior == SLEEP_INHIBIT_LOCK_NOTIFY)
|
|
||||||
inhibitSleep();
|
|
||||||
|
|
||||||
static const auto UNLOCKCMD = g_pConfigManager->getValue<Hyprlang::STRING>("general:on_unlock_cmd");
|
|
||||||
if (!std::string{*UNLOCKCMD}.empty())
|
|
||||||
spawn(*UNLOCKCMD);
|
|
||||||
}
|
|
||||||
|
|
||||||
CHypridle::SDbusInhibitCookie CHypridle::getDbusInhibitCookie(uint32_t cookie) {
|
CHypridle::SDbusInhibitCookie CHypridle::getDbusInhibitCookie(uint32_t cookie) {
|
||||||
for (auto& c : m_sDBUSState.inhibitCookies) {
|
for (auto& c : m_sDBUSState.inhibitCookies) {
|
||||||
if (c.cookie == cookie)
|
if (c.cookie == cookie)
|
||||||
|
|
@ -362,7 +335,8 @@ void CHypridle::registerDbusInhibitCookie(CHypridle::SDbusInhibitCookie& cookie)
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CHypridle::unregisterDbusInhibitCookie(const CHypridle::SDbusInhibitCookie& cookie) {
|
bool CHypridle::unregisterDbusInhibitCookie(const CHypridle::SDbusInhibitCookie& cookie) {
|
||||||
const auto IT = std::ranges::find_if(m_sDBUSState.inhibitCookies, [&cookie](const CHypridle::SDbusInhibitCookie& item) { return item.cookie == cookie.cookie; });
|
const auto IT = std::find_if(m_sDBUSState.inhibitCookies.begin(), m_sDBUSState.inhibitCookies.end(),
|
||||||
|
[&cookie](const CHypridle::SDbusInhibitCookie& item) { return item.cookie == cookie.cookie; });
|
||||||
|
|
||||||
if (IT == m_sDBUSState.inhibitCookies.end())
|
if (IT == m_sDBUSState.inhibitCookies.end())
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -371,14 +345,21 @@ bool CHypridle::unregisterDbusInhibitCookie(const CHypridle::SDbusInhibitCookie&
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t CHypridle::unregisterDbusInhibitCookies(const std::string& ownerID) {
|
bool CHypridle::unregisterDbusInhibitCookies(const std::string& ownerID) {
|
||||||
return std::erase_if(m_sDBUSState.inhibitCookies, [&ownerID](const CHypridle::SDbusInhibitCookie& item) { return item.ownerID == ownerID; });
|
const auto IT = std::remove_if(m_sDBUSState.inhibitCookies.begin(), m_sDBUSState.inhibitCookies.end(),
|
||||||
|
[&ownerID](const CHypridle::SDbusInhibitCookie& item) { return item.ownerID == ownerID; });
|
||||||
|
|
||||||
|
if (IT == m_sDBUSState.inhibitCookies.end())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
m_sDBUSState.inhibitCookies.erase(IT, m_sDBUSState.inhibitCookies.end());
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handleDbusLogin(sdbus::Message msg) {
|
static void handleDbusLogin(sdbus::Message msg) {
|
||||||
// lock & unlock
|
// lock & unlock
|
||||||
static const auto LOCKCMD = g_pConfigManager->getValue<Hyprlang::STRING>("general:lock_cmd");
|
static auto* const PLOCKCMD = (Hyprlang::STRING const*)g_pConfigManager->getValuePtr("general:lock_cmd");
|
||||||
static const auto UNLOCKCMD = g_pConfigManager->getValue<Hyprlang::STRING>("general:unlock_cmd");
|
static auto* const PUNLOCKCMD = (Hyprlang::STRING const*)g_pConfigManager->getValuePtr("general:unlock_cmd");
|
||||||
|
|
||||||
Debug::log(LOG, "Got dbus .Session");
|
Debug::log(LOG, "Got dbus .Session");
|
||||||
|
|
||||||
|
|
@ -386,16 +367,16 @@ static void handleDbusLogin(sdbus::Message msg) {
|
||||||
if (MEMBER == "Lock") {
|
if (MEMBER == "Lock") {
|
||||||
Debug::log(LOG, "Got Lock from dbus");
|
Debug::log(LOG, "Got Lock from dbus");
|
||||||
|
|
||||||
if (!std::string{*LOCKCMD}.empty()) {
|
if (!std::string{*PLOCKCMD}.empty()) {
|
||||||
Debug::log(LOG, "Locking with {}", *LOCKCMD);
|
Debug::log(LOG, "Locking with {}", *PLOCKCMD);
|
||||||
spawn(*LOCKCMD);
|
spawn(*PLOCKCMD);
|
||||||
}
|
}
|
||||||
} else if (MEMBER == "Unlock") {
|
} else if (MEMBER == "Unlock") {
|
||||||
Debug::log(LOG, "Got Unlock from dbus");
|
Debug::log(LOG, "Got Unlock from dbus");
|
||||||
|
|
||||||
if (!std::string{*UNLOCKCMD}.empty()) {
|
if (!std::string{*PUNLOCKCMD}.empty()) {
|
||||||
Debug::log(LOG, "Unlocking with {}", *UNLOCKCMD);
|
Debug::log(LOG, "Locking with {}", *PUNLOCKCMD);
|
||||||
spawn(*UNLOCKCMD);
|
spawn(*PUNLOCKCMD);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -409,24 +390,21 @@ static void handleDbusSleep(sdbus::Message msg) {
|
||||||
bool toSleep = true;
|
bool toSleep = true;
|
||||||
msg >> toSleep;
|
msg >> toSleep;
|
||||||
|
|
||||||
static const auto SLEEPCMD = g_pConfigManager->getValue<Hyprlang::STRING>("general:before_sleep_cmd");
|
static auto* const PSLEEPCMD = (Hyprlang::STRING const*)g_pConfigManager->getValuePtr("general:before_sleep_cmd");
|
||||||
static const auto AFTERSLEEPCMD = g_pConfigManager->getValue<Hyprlang::STRING>("general:after_sleep_cmd");
|
static auto* const PAFTERSLEEPCMD = (Hyprlang::STRING const*)g_pConfigManager->getValuePtr("general:after_sleep_cmd");
|
||||||
|
|
||||||
Debug::log(LOG, "Got PrepareForSleep from dbus with sleep {}", toSleep);
|
Debug::log(LOG, "Got PrepareForSleep from dbus with sleep {}", toSleep);
|
||||||
|
|
||||||
std::string cmd = toSleep ? *SLEEPCMD : *AFTERSLEEPCMD;
|
std::string cmd = toSleep ? *PSLEEPCMD : *PAFTERSLEEPCMD;
|
||||||
|
|
||||||
if (!toSleep)
|
if (cmd.empty())
|
||||||
g_pHypridle->handleInhibitOnDbusSleep(toSleep);
|
return;
|
||||||
|
|
||||||
if (!cmd.empty())
|
Debug::log(LOG, "Running: {}", cmd);
|
||||||
spawn(cmd);
|
spawn(cmd);
|
||||||
|
|
||||||
if (toSleep)
|
|
||||||
g_pHypridle->handleInhibitOnDbusSleep(toSleep);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handleDbusBlockInhibits(const std::string& inhibits) {
|
void handleDbusBlockInhibits(const std::string& inhibits) {
|
||||||
static auto inhibited = false;
|
static auto inhibited = false;
|
||||||
// BlockInhibited is a colon separated list of inhibit types. Wrapping in additional colons allows for easier checking if there are active inhibits we are interested in
|
// BlockInhibited is a colon separated list of inhibit types. Wrapping in additional colons allows for easier checking if there are active inhibits we are interested in
|
||||||
auto inhibits_ = ":" + inhibits + ":";
|
auto inhibits_ = ":" + inhibits + ":";
|
||||||
|
|
@ -452,9 +430,8 @@ static void handleDbusBlockInhibitsPropertyChanged(sdbus::Message msg) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t handleDbusScreensaver(std::string app, std::string reason, uint32_t cookie, bool inhibit, const char* sender) {
|
static int handleDbusScreensaver(std::string app, std::string reason, uint32_t cookie, bool inhibit, const char* sender) {
|
||||||
std::string ownerID = sender;
|
std::string ownerID = sender;
|
||||||
bool cookieFound = false;
|
|
||||||
|
|
||||||
if (!inhibit) {
|
if (!inhibit) {
|
||||||
Debug::log(TRACE, "Read uninhibit cookie: {}", cookie);
|
Debug::log(TRACE, "Read uninhibit cookie: {}", cookie);
|
||||||
|
|
@ -465,7 +442,6 @@ static uint32_t handleDbusScreensaver(std::string app, std::string reason, uint3
|
||||||
app = COOKIE.app;
|
app = COOKIE.app;
|
||||||
reason = COOKIE.reason;
|
reason = COOKIE.reason;
|
||||||
ownerID = COOKIE.ownerID;
|
ownerID = COOKIE.ownerID;
|
||||||
cookieFound = true;
|
|
||||||
|
|
||||||
if (!g_pHypridle->unregisterDbusInhibitCookie(COOKIE))
|
if (!g_pHypridle->unregisterDbusInhibitCookie(COOKIE))
|
||||||
Debug::log(WARN, "BUG THIS: attempted to unregister unknown cookie");
|
Debug::log(WARN, "BUG THIS: attempted to unregister unknown cookie");
|
||||||
|
|
@ -476,13 +452,13 @@ static uint32_t handleDbusScreensaver(std::string app, std::string reason, uint3
|
||||||
|
|
||||||
if (inhibit)
|
if (inhibit)
|
||||||
g_pHypridle->onInhibit(true);
|
g_pHypridle->onInhibit(true);
|
||||||
else if (cookieFound)
|
else
|
||||||
g_pHypridle->onInhibit(false);
|
g_pHypridle->onInhibit(false);
|
||||||
|
|
||||||
static uint32_t cookieID = 1337;
|
static int cookieID = 1337;
|
||||||
|
|
||||||
if (inhibit) {
|
if (inhibit) {
|
||||||
auto cookie = CHypridle::SDbusInhibitCookie{.cookie = cookieID, .app = app, .reason = reason, .ownerID = ownerID};
|
auto cookie = CHypridle::SDbusInhibitCookie{uint32_t{cookieID}, app, reason, ownerID};
|
||||||
|
|
||||||
Debug::log(LOG, "Cookie {} sent", cookieID);
|
Debug::log(LOG, "Cookie {} sent", cookieID);
|
||||||
|
|
||||||
|
|
@ -501,17 +477,15 @@ static void handleDbusNameOwnerChanged(sdbus::Message msg) {
|
||||||
if (!newOwner.empty())
|
if (!newOwner.empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
size_t removed = g_pHypridle->unregisterDbusInhibitCookies(oldOwner);
|
if (g_pHypridle->unregisterDbusInhibitCookies(oldOwner)) {
|
||||||
if (removed > 0) {
|
|
||||||
Debug::log(LOG, "App with owner {} disconnected", oldOwner);
|
Debug::log(LOG, "App with owner {} disconnected", oldOwner);
|
||||||
for (size_t i = 0; i < removed; i++)
|
g_pHypridle->onInhibit(false);
|
||||||
g_pHypridle->onInhibit(false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CHypridle::setupDBUS() {
|
void CHypridle::setupDBUS() {
|
||||||
static const auto IGNOREDBUSINHIBIT = g_pConfigManager->getValue<Hyprlang::INT>("general:ignore_dbus_inhibit");
|
static auto const IGNORE_DBUS_INHIBIT = **(Hyprlang::INT* const*)g_pConfigManager->getValuePtr("general:ignore_dbus_inhibit");
|
||||||
static const auto IGNORESYSTEMDINHIBIT = g_pConfigManager->getValue<Hyprlang::INT>("general:ignore_systemd_inhibit");
|
static auto const IGNORE_SYSTEMD_INHIBIT = **(Hyprlang::INT* const*)g_pConfigManager->getValuePtr("general:ignore_systemd_inhibit");
|
||||||
|
|
||||||
auto systemConnection = sdbus::createSystemBusConnection();
|
auto systemConnection = sdbus::createSystemBusConnection();
|
||||||
auto proxy = sdbus::createProxy(*systemConnection, sdbus::ServiceName{"org.freedesktop.login1"}, sdbus::ObjectPath{"/org/freedesktop/login1"});
|
auto proxy = sdbus::createProxy(*systemConnection, sdbus::ServiceName{"org.freedesktop.login1"}, sdbus::ObjectPath{"/org/freedesktop/login1"});
|
||||||
|
|
@ -522,12 +496,11 @@ void CHypridle::setupDBUS() {
|
||||||
|
|
||||||
m_sDBUSState.connection->addMatch("type='signal',path='" + path + "',interface='org.freedesktop.login1.Session'", ::handleDbusLogin);
|
m_sDBUSState.connection->addMatch("type='signal',path='" + path + "',interface='org.freedesktop.login1.Session'", ::handleDbusLogin);
|
||||||
m_sDBUSState.connection->addMatch("type='signal',path='/org/freedesktop/login1',interface='org.freedesktop.login1.Manager'", ::handleDbusSleep);
|
m_sDBUSState.connection->addMatch("type='signal',path='/org/freedesktop/login1',interface='org.freedesktop.login1.Manager'", ::handleDbusSleep);
|
||||||
m_sDBUSState.login = sdbus::createProxy(*m_sDBUSState.connection, sdbus::ServiceName{"org.freedesktop.login1"}, sdbus::ObjectPath{"/org/freedesktop/login1"});
|
|
||||||
} catch (std::exception& e) { Debug::log(WARN, "Couldn't connect to logind service ({})", e.what()); }
|
} catch (std::exception& e) { Debug::log(WARN, "Couldn't connect to logind service ({})", e.what()); }
|
||||||
|
|
||||||
Debug::log(LOG, "Using dbus path {}", path.c_str());
|
Debug::log(LOG, "Using dbus path {}", path.c_str());
|
||||||
|
|
||||||
if (!*IGNORESYSTEMDINHIBIT) {
|
if (!IGNORE_SYSTEMD_INHIBIT) {
|
||||||
m_sDBUSState.connection->addMatch("type='signal',path='/org/freedesktop/login1',interface='org.freedesktop.DBus.Properties'", ::handleDbusBlockInhibitsPropertyChanged);
|
m_sDBUSState.connection->addMatch("type='signal',path='/org/freedesktop/login1',interface='org.freedesktop.DBus.Properties'", ::handleDbusBlockInhibitsPropertyChanged);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
@ -536,7 +509,7 @@ void CHypridle::setupDBUS() {
|
||||||
} catch (std::exception& e) { Debug::log(WARN, "Couldn't retrieve current systemd inhibits ({})", e.what()); }
|
} catch (std::exception& e) { Debug::log(WARN, "Couldn't retrieve current systemd inhibits ({})", e.what()); }
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!*IGNOREDBUSINHIBIT) {
|
if (!IGNORE_DBUS_INHIBIT) {
|
||||||
// attempt to register as ScreenSaver
|
// attempt to register as ScreenSaver
|
||||||
std::string paths[] = {
|
std::string paths[] = {
|
||||||
"/org/freedesktop/ScreenSaver",
|
"/org/freedesktop/ScreenSaver",
|
||||||
|
|
@ -564,80 +537,8 @@ void CHypridle::setupDBUS() {
|
||||||
|
|
||||||
m_sDBUSState.screenSaverServiceConnection->addMatch("type='signal',sender='org.freedesktop.DBus',interface='org.freedesktop.DBus',member='NameOwnerChanged'",
|
m_sDBUSState.screenSaverServiceConnection->addMatch("type='signal',sender='org.freedesktop.DBus',interface='org.freedesktop.DBus',member='NameOwnerChanged'",
|
||||||
::handleDbusNameOwnerChanged);
|
::handleDbusNameOwnerChanged);
|
||||||
} catch (sdbus::Error& e) {
|
} catch (std::exception& e) { Debug::log(ERR, "Couldn't connect to session dbus\nerr: {}", e.what()); }
|
||||||
if (e.getName() == sdbus::Error::Name{"org.freedesktop.DBus.Error.FileExists"}) {
|
|
||||||
Debug::log(ERR, "Another service is already providing the org.freedesktop.ScreenSaver interface");
|
|
||||||
Debug::log(ERR, "Is hypridle already running?");
|
|
||||||
} else
|
|
||||||
Debug::log(ERR, "Failed to connect to ScreenSaver service\nerr: {}", e.what());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
systemConnection.reset();
|
systemConnection.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CHypridle::handleInhibitOnDbusSleep(bool toSleep) {
|
|
||||||
if (m_inhibitSleepBehavior == SLEEP_INHIBIT_NONE || //
|
|
||||||
m_inhibitSleepBehavior == SLEEP_INHIBIT_LOCK_NOTIFY // Sleep inhibition handled via onLocked/onUnlocked
|
|
||||||
)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!toSleep)
|
|
||||||
inhibitSleep();
|
|
||||||
else
|
|
||||||
uninhibitSleep();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CHypridle::inhibitSleep() {
|
|
||||||
if (!m_sDBUSState.login) {
|
|
||||||
Debug::log(WARN, "Can't inhibit sleep. Dbus logind interface is not available.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_sDBUSState.sleepInhibitFd.isValid()) {
|
|
||||||
Debug::log(WARN, "Called inhibitSleep, but previous sleep inhibitor is still active!");
|
|
||||||
m_sDBUSState.sleepInhibitFd.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
auto method = m_sDBUSState.login->createMethodCall(sdbus::InterfaceName{"org.freedesktop.login1.Manager"}, sdbus::MethodName{"Inhibit"});
|
|
||||||
method << "sleep";
|
|
||||||
method << "hypridle";
|
|
||||||
method << "Hypridle wants to delay sleep until it's before_sleep handling is done.";
|
|
||||||
method << "delay";
|
|
||||||
|
|
||||||
try {
|
|
||||||
auto reply = m_sDBUSState.login->callMethod(method);
|
|
||||||
|
|
||||||
if (!reply || !reply.isValid()) {
|
|
||||||
Debug::log(ERR, "Failed to inhibit sleep");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (reply.isEmpty()) {
|
|
||||||
Debug::log(ERR, "Failed to inhibit sleep, empty reply");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
sdbus::UnixFd fd;
|
|
||||||
// This calls dup on the fd, no F_DUPFD_CLOEXEC :(
|
|
||||||
// There seems to be no way to get the file descriptor out of the reply other than that.
|
|
||||||
reply >> fd;
|
|
||||||
|
|
||||||
// Setting the O_CLOEXEC flag does not work for some reason. Instead we make our own dupe and close the one from UnixFd.
|
|
||||||
auto immidiateFD = Hyprutils::OS::CFileDescriptor(fd.release());
|
|
||||||
m_sDBUSState.sleepInhibitFd = immidiateFD.duplicate(F_DUPFD_CLOEXEC);
|
|
||||||
immidiateFD.reset(); // close the fd that was opened with dup
|
|
||||||
|
|
||||||
Debug::log(LOG, "Inhibited sleep with fd {}", m_sDBUSState.sleepInhibitFd.get());
|
|
||||||
} catch (const std::exception& e) { Debug::log(ERR, "Failed to inhibit sleep ({})", e.what()); }
|
|
||||||
}
|
|
||||||
|
|
||||||
void CHypridle::uninhibitSleep() {
|
|
||||||
if (!m_sDBUSState.sleepInhibitFd.isValid()) {
|
|
||||||
Debug::log(ERR, "No sleep inhibitor fd to release");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Debug::log(LOG, "Releasing the sleep inhibitor!");
|
|
||||||
m_sDBUSState.sleepInhibitFd.reset();
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -2,25 +2,20 @@
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <wayland-client.h>
|
||||||
#include <sdbus-c++/sdbus-c++.h>
|
#include <sdbus-c++/sdbus-c++.h>
|
||||||
#include <hyprutils/os/FileDescriptor.hpp>
|
|
||||||
#include <condition_variable>
|
#include <condition_variable>
|
||||||
|
|
||||||
#include "wayland.hpp"
|
#include "ext-idle-notify-v1-protocol.h"
|
||||||
#include "ext-idle-notify-v1.hpp"
|
|
||||||
#include "hyprland-lock-notify-v1.hpp"
|
|
||||||
|
|
||||||
#include "../defines.hpp"
|
|
||||||
|
|
||||||
class CHypridle {
|
class CHypridle {
|
||||||
public:
|
public:
|
||||||
CHypridle();
|
CHypridle();
|
||||||
|
|
||||||
struct SIdleListener {
|
struct SIdleListener {
|
||||||
SP<CCExtIdleNotificationV1> notification = nullptr;
|
ext_idle_notification_v1* notification = nullptr;
|
||||||
std::string onTimeout = "";
|
std::string onTimeout = "";
|
||||||
std::string onRestore = "";
|
std::string onRestore = "";
|
||||||
bool ignoreInhibit = false;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SDbusInhibitCookie {
|
struct SDbusInhibitCookie {
|
||||||
|
|
@ -38,17 +33,10 @@ class CHypridle {
|
||||||
|
|
||||||
void onInhibit(bool lock);
|
void onInhibit(bool lock);
|
||||||
|
|
||||||
void onLocked();
|
|
||||||
void onUnlocked();
|
|
||||||
|
|
||||||
SDbusInhibitCookie getDbusInhibitCookie(uint32_t cookie);
|
SDbusInhibitCookie getDbusInhibitCookie(uint32_t cookie);
|
||||||
void registerDbusInhibitCookie(SDbusInhibitCookie& cookie);
|
void registerDbusInhibitCookie(SDbusInhibitCookie& cookie);
|
||||||
bool unregisterDbusInhibitCookie(const SDbusInhibitCookie& cookie);
|
bool unregisterDbusInhibitCookie(const SDbusInhibitCookie& cookie);
|
||||||
size_t unregisterDbusInhibitCookies(const std::string& ownerID);
|
bool unregisterDbusInhibitCookies(const std::string& ownerID);
|
||||||
|
|
||||||
void handleInhibitOnDbusSleep(bool toSleep);
|
|
||||||
void inhibitSleep();
|
|
||||||
void uninhibitSleep();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void setupDBUS();
|
void setupDBUS();
|
||||||
|
|
@ -56,25 +44,16 @@ class CHypridle {
|
||||||
|
|
||||||
bool m_bTerminate = false;
|
bool m_bTerminate = false;
|
||||||
bool isIdled = false;
|
bool isIdled = false;
|
||||||
bool m_isLocked = false;
|
|
||||||
int64_t m_iInhibitLocks = 0;
|
int64_t m_iInhibitLocks = 0;
|
||||||
|
|
||||||
enum {
|
|
||||||
SLEEP_INHIBIT_NONE,
|
|
||||||
SLEEP_INHIBIT_NORMAL,
|
|
||||||
SLEEP_INHIBIT_LOCK_NOTIFY,
|
|
||||||
} m_inhibitSleepBehavior;
|
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
wl_display* display = nullptr;
|
wl_display* display = nullptr;
|
||||||
SP<CCWlRegistry> registry = nullptr;
|
wl_registry* registry = nullptr;
|
||||||
SP<CCWlSeat> seat = nullptr;
|
wl_seat* seat = nullptr;
|
||||||
SP<CCHyprlandLockNotifierV1> lockNotifier = nullptr;
|
|
||||||
SP<CCHyprlandLockNotificationV1> lockNotification = nullptr;
|
|
||||||
} m_sWaylandState;
|
} m_sWaylandState;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
SP<CCExtIdleNotifierV1> notifier = nullptr;
|
ext_idle_notifier_v1* notifier = nullptr;
|
||||||
|
|
||||||
std::vector<SIdleListener> listeners;
|
std::vector<SIdleListener> listeners;
|
||||||
} m_sWaylandIdleState;
|
} m_sWaylandIdleState;
|
||||||
|
|
@ -82,10 +61,8 @@ class CHypridle {
|
||||||
struct {
|
struct {
|
||||||
std::unique_ptr<sdbus::IConnection> connection;
|
std::unique_ptr<sdbus::IConnection> connection;
|
||||||
std::unique_ptr<sdbus::IConnection> screenSaverServiceConnection;
|
std::unique_ptr<sdbus::IConnection> screenSaverServiceConnection;
|
||||||
std::unique_ptr<sdbus::IProxy> login;
|
|
||||||
std::vector<std::unique_ptr<sdbus::IObject>> screenSaverObjects;
|
std::vector<std::unique_ptr<sdbus::IObject>> screenSaverObjects;
|
||||||
std::vector<SDbusInhibitCookie> inhibitCookies;
|
std::vector<SDbusInhibitCookie> inhibitCookies;
|
||||||
Hyprutils::OS::CFileDescriptor sleepInhibitFd;
|
|
||||||
} m_sDBUSState;
|
} m_sDBUSState;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
|
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
#include "wayland.hpp"
|
|
||||||
#include "ext-idle-notify-v1.hpp"
|
|
||||||
#include "hyprland-lock-notify-v1.hpp"
|
|
||||||
|
|
||||||
#include <hyprutils/memory/WeakPtr.hpp>
|
|
||||||
using namespace Hyprutils::Memory;
|
|
||||||
#define SP CSharedPointer
|
|
||||||
#define WP CWeakPointer
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
#include <filesystem>
|
|
||||||
|
|
||||||
#include "MiscFunctions.hpp"
|
|
||||||
|
|
||||||
std::string absolutePath(const std::string& rawpath, const std::string& currentDir) {
|
|
||||||
std::filesystem::path path(rawpath);
|
|
||||||
|
|
||||||
// Handling where rawpath starts with '~'
|
|
||||||
if (!rawpath.empty() && rawpath[0] == '~') {
|
|
||||||
static const char* const ENVHOME = getenv("HOME");
|
|
||||||
path = std::filesystem::path(ENVHOME) / path.relative_path().string().substr(2);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handling e.g. ./, ../
|
|
||||||
if (path.is_relative())
|
|
||||||
return std::filesystem::weakly_canonical(std::filesystem::path(currentDir) / path);
|
|
||||||
else
|
|
||||||
return std::filesystem::weakly_canonical(path);
|
|
||||||
}
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
std::string absolutePath(const std::string&, const std::string&);
|
|
||||||
17
src/main.cpp
17
src/main.cpp
|
|
@ -15,11 +15,6 @@ int main(int argc, char** argv, char** envp) {
|
||||||
else if (arg == "--quiet" || arg == "-q")
|
else if (arg == "--quiet" || arg == "-q")
|
||||||
Debug::quiet = true;
|
Debug::quiet = true;
|
||||||
|
|
||||||
else if (arg == "--version" || arg == "-V") {
|
|
||||||
Debug::log(NONE, "hypridle v{}", HYPRIDLE_VERSION);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (arg == "--config" || arg == "-c") {
|
else if (arg == "--config" || arg == "-c") {
|
||||||
if (i + 1 >= argc) {
|
if (i + 1 >= argc) {
|
||||||
Debug::log(NONE, "After " + arg + " you should provide a path to a config file.");
|
Debug::log(NONE, "After " + arg + " you should provide a path to a config file.");
|
||||||
|
|
@ -37,18 +32,6 @@ int main(int argc, char** argv, char** envp) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (arg == "--help" || arg == "-h") {
|
|
||||||
Debug::log(NONE,
|
|
||||||
"Usage: hypridle [options]\n"
|
|
||||||
"Options:\n"
|
|
||||||
" -v, --verbose Enable verbose logging\n"
|
|
||||||
" -q, --quiet Suppress all output except errors\n"
|
|
||||||
" -V, --version Show version information\n"
|
|
||||||
" -c, --config <path> Specify a custom config file path\n"
|
|
||||||
" -h, --help Show this help message");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue