File hypridle-0.1.6.obscpio of Package hypridle

07070100000000000081A400000000000000000000000167E6AF620000070E000000000000000000000000000000000000001D00000000hypridle-0.1.6/.clang-format---
Language: Cpp
BasedOnStyle: LLVM

AccessModifierOffset: -2
AlignAfterOpenBracket: Align
AlignConsecutiveMacros: true
AlignConsecutiveAssignments: true
AlignEscapedNewlines: Right
AlignOperands: false
AlignTrailingComments: true
AllowAllArgumentsOnNextLine: true
AllowAllConstructorInitializersOnNextLine: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: true
AllowShortCaseLabelsOnASingleLine: true
AllowShortFunctionsOnASingleLine: Empty
AllowShortIfStatementsOnASingleLine: Never
AllowShortLambdasOnASingleLine: All
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: Yes
BreakBeforeBraces: Attach
BreakBeforeTernaryOperators: false
BreakConstructorInitializers: AfterColon
ColumnLimit: 180
CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: false
ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: false
IncludeBlocks: Preserve
IndentCaseLabels: true
IndentWidth: 4
PointerAlignment: Left
ReflowComments: false
SortIncludes: false
SortUsingDeclarations: false
SpaceAfterCStyleCast: false
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: true
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatements
SpaceBeforeRangeBasedForLoopColon: true
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: false
SpacesInCStyleCastParentheses: false
SpacesInContainerLiterals: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: Auto
TabWidth: 4
UseTab: Never

AllowShortEnumsOnASingleLine: false

BraceWrapping:
  AfterEnum: false

AlignConsecutiveDeclarations: AcrossEmptyLines

NamespaceIndentation: All
07070100000001000081A400000000000000000000000167E6AF6200000EB8000000000000000000000000000000000000001B00000000hypridle-0.1.6/.clang-tidyWarningsAsErrors: '*'
HeaderFilterRegex: '.*\.hpp'
FormatStyle: file
Checks: >
  -*,
  bugprone-*,
  -bugprone-easily-swappable-parameters,
  -bugprone-forward-declararion-namespace,
  -bugprone-forward-declararion-namespace,
  -bugprone-macro-parentheses,
  -bugprone-narrowing-conversions,
  -bugprone-branch-clone,
  -bugprone-assignment-in-if-condition,
  concurrency-*,
  -concurrency-mt-unsafe,
  cppcoreguidelines-*,
  -cppcoreguidelines-owning-memory,
  -cppcoreguidelines-avoid-magic-numbers,
  -cppcoreguidelines-pro-bounds-constant-array-index,
  -cppcoreguidelines-avoid-const-or-ref-data-members,
  -cppcoreguidelines-non-private-member-variables-in-classes,
  -cppcoreguidelines-avoid-goto,
  -cppcoreguidelines-pro-bounds-array-to-pointer-decay,
  -cppcoreguidelines-avoid-do-while,
  -cppcoreguidelines-avoid-non-const-global-variables,
  -cppcoreguidelines-special-member-functions,
  -cppcoreguidelines-explicit-virtual-functions,
  -cppcoreguidelines-avoid-c-arrays,
  -cppcoreguidelines-pro-bounds-pointer-arithmetic,
  -cppcoreguidelines-narrowing-conversions,
  -cppcoreguidelines-pro-type-union-access,
  -cppcoreguidelines-pro-type-member-init,
  -cppcoreguidelines-macro-usage,
  -cppcoreguidelines-macro-to-enum,
  -cppcoreguidelines-init-variables,
  -cppcoreguidelines-pro-type-cstyle-cast,
  -cppcoreguidelines-pro-type-vararg,
  -cppcoreguidelines-pro-type-reinterpret-cast,
  google-global-names-in-headers,
  -google-readability-casting,
  google-runtime-operator,
  misc-*,
  -misc-unused-parameters,
  -misc-no-recursion,
  -misc-non-private-member-variables-in-classes,
  -misc-include-cleaner,
  -misc-use-anonymous-namespace,
  -misc-const-correctness,
  modernize-*,
  -modernize-return-braced-init-list,
  -modernize-use-trailing-return-type,
  -modernize-use-using,
  -modernize-use-override,
  -modernize-avoid-c-arrays,
  -modernize-macro-to-enum,
  -modernize-loop-convert,
  -modernize-use-nodiscard,
  -modernize-pass-by-value,
  -modernize-use-auto,
  performance-*,
  -performance-avoid-endl,
  -performance-unnecessary-value-param,
  portability-std-allocator-const,
  readability-*,
  -readability-function-cognitive-complexity,
  -readability-function-size,
  -readability-identifier-length,
  -readability-magic-numbers,
  -readability-uppercase-literal-suffix,
  -readability-braces-around-statements,
  -readability-redundant-access-specifiers,
  -readability-else-after-return,
  -readability-container-data-pointer,
  -readability-implicit-bool-conversion,
  -readability-avoid-nested-conditional-operator,
  -readability-redundant-member-init,
  -readability-redundant-string-init,
  -readability-avoid-const-params-in-decls,
  -readability-named-parameter,
  -readability-convert-member-functions-to-static,
  -readability-qualified-auto,
  -readability-make-member-function-const,
  -readability-isolate-declaration,
  -readability-inconsistent-declaration-parameter-name,
  -clang-diagnostic-error,

CheckOptions:
  performance-for-range-copy.WarnOnAllAutoCopies: true
  performance-inefficient-string-concatenation.StrictMode: true
  readability-braces-around-statements.ShortStatementLines: 0
  readability-identifier-naming.ClassCase: CamelCase
  readability-identifier-naming.ClassIgnoredRegexp: I.*
  readability-identifier-naming.ClassPrefix: C # We can't use regex here?!?!?!?
  readability-identifier-naming.EnumCase: CamelCase
  readability-identifier-naming.EnumPrefix: e
  readability-identifier-naming.EnumConstantCase: UPPER_CASE
  readability-identifier-naming.FunctionCase: camelBack
  readability-identifier-naming.NamespaceCase: CamelCase
  readability-identifier-naming.NamespacePrefix: N
  readability-identifier-naming.StructPrefix: S
  readability-identifier-naming.StructCase: CamelCase
07070100000002000041ED00000000000000000000000267E6AF6200000000000000000000000000000000000000000000001700000000hypridle-0.1.6/.github07070100000003000041ED00000000000000000000000267E6AF6200000000000000000000000000000000000000000000002100000000hypridle-0.1.6/.github/workflows07070100000004000081A400000000000000000000000167E6AF62000001B3000000000000000000000000000000000000002900000000hypridle-0.1.6/.github/workflows/nix.ymlname: Build

on: [push, pull_request, workflow_dispatch]
jobs:
  nix:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v3

    - uses: DeterminateSystems/nix-installer-action@main

    # not needed (yet)
    # - uses: cachix/cachix-action@v12
    #   with:
    #     name: hyprland
    #     authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'

    - name: Build
      run: nix flake check --print-build-logs --keep-going

07070100000005000081A400000000000000000000000167E6AF620000004B000000000000000000000000000000000000001A00000000hypridle-0.1.6/.gitignore.vscode/
build/
protocols/
.clangd/
.direnv/
.cache/
compile_commands.json
07070100000006000081A400000000000000000000000167E6AF6200000DF0000000000000000000000000000000000000001E00000000hypridle-0.1.6/CMakeLists.txtcmake_minimum_required(VERSION 3.19)

file(READ "${CMAKE_SOURCE_DIR}/VERSION" VER_RAW)
string(STRIP ${VER_RAW} VERSION)

project(
  hypridle
  DESCRIPTION "An idle management daemon for Hyprland"
  VERSION ${VERSION})

set(CMAKE_MESSAGE_LOG_LEVEL "STATUS")

if(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG)
  message(STATUS "Configuring hypridle in Debug with CMake")
  add_compile_definitions(HYPRLAND_DEBUG)
else()
  add_compile_options(-O3)
  message(STATUS "Configuring hypridle in Release with CMake")
endif()

add_compile_definitions(HYPRIDLE_VERSION="${VERSION}")

include_directories(. "protocols/")

include(GNUInstallDirs)

# configure
set(CMAKE_CXX_STANDARD 23)
set(CMAKE_EXPORT_COMPILE_COMMANDS TRUE)
add_compile_options(-Wall -Wextra -Wuseless-cast -Wno-unused-parameter
                    -Wno-unused-value -Wno-missing-field-initializers)
configure_file(systemd/hypridle.service.in systemd/hypridle.service @ONLY)

# dependencies
message(STATUS "Checking deps...")

find_package(Threads REQUIRED)
find_package(PkgConfig REQUIRED)
find_package(hyprwayland-scanner 0.4.4 REQUIRED)
pkg_check_modules(
  deps
  REQUIRED
  IMPORTED_TARGET
  wayland-client
  wayland-protocols
  hyprlang>=0.6.0
  hyprutils>=0.2.0
  sdbus-c++>=0.2.0)

file(GLOB_RECURSE SRCFILES CONFIGURE_DEPENDS "src/*.cpp")
add_executable(hypridle ${SRCFILES})
target_link_libraries(hypridle PRIVATE rt Threads::Threads PkgConfig::deps)

# protocols
pkg_get_variable(WAYLAND_PROTOCOLS_DIR wayland-protocols pkgdatadir)
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)
pkg_get_variable(HYPRLAND_PROTOCOLS hyprland-protocols pkgdatadir)
message(STATUS "Found hyprland-protocols at ${HYPRLAND_PROTOCOLS}")

function(protocolnew protoPath protoName external)
  if(external)
    set(path ${protoPath})
  else()
    set(path ${WAYLAND_PROTOCOLS_DIR}/${protoPath})
  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()

make_directory(${CMAKE_SOURCE_DIR}/protocols) # we don't ship any custom ones so

protocolwayland()

protocolnew("staging/ext-idle-notify" "ext-idle-notify-v1" false)
protocolnew("${HYPRLAND_PROTOCOLS}/protocols" "hyprland-lock-notify-v1" true)

# Installation
install(TARGETS hypridle)
install(FILES ${CMAKE_BINARY_DIR}/systemd/hypridle.service
        DESTINATION "lib/systemd/user")

install(
  FILES ${CMAKE_SOURCE_DIR}/assets/example.conf
  DESTINATION ${CMAKE_INSTALL_FULL_DATAROOTDIR}/hypr
  RENAME hypridle.conf)
07070100000007000081A400000000000000000000000167E6AF62000005DF000000000000000000000000000000000000001700000000hypridle-0.1.6/LICENSEBSD 3-Clause License

Copyright (c) 2024, Hypr Development

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this
   list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.

3. Neither the name of the copyright holder nor the names of its
   contributors may be used to endorse or promote products derived from
   this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
07070100000008000081A400000000000000000000000167E6AF62000008FD000000000000000000000000000000000000001900000000hypridle-0.1.6/README.md# hypridle
Hyprland's idle daemon

## Features
 - based on the `ext-idle-notify-v1` wayland protocol
 - support for dbus' loginctl commands (lock / unlock / before-sleep)
 - support for dbus' inhibit (used by e.g. firefox / steam)

## Configuration

Configuration is done via `~/.config/hypr/hypridle.conf` in the standard
hyprland syntax.

```ini
general {
    lock_cmd = notify-send "lock!"          # dbus/sysd lock command (loginctl lock-session)
    unlock_cmd = notify-send "unlock!"      # same as above, but unlock
    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 {
    timeout = 500                            # in seconds
    on-timeout = notify-send "You are idle!" # command to run when timeout has passed
    on-resume = notify-send "Welcome back!"  # command to run when activity is detected after timeout has fired.
}
```

You can add as many listeners as you please. Omitting `on-timeout` or `on-resume` (or leaving them empty)
will make those events ignored.

## Dependencies
 - wayland
 - wayland-protocols
 - hyprlang >= 0.4.0
 - sdbus-c++
 - hyprwayland-scanner

## Building & Installation

### Building:
```sh
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -S . -B ./build
cmake --build ./build --config Release --target hypridle -j`nproc 2>/dev/null || getconf _NPROCESSORS_CONF`
```

### Installation:
```sh
sudo cmake --install build
```

### Usage:

Hypridle should ideally be launched after logging in. This can be done by your compositor or by systemd.
For example, for Hyprland, use the following in your `hyprland.conf`.
```hyprlang
exec-once = hypridle
```
If, instead, you want to have systemd do this for you, you'll just need to enable the service using
```sh
systemctl --user enable --now hypridle.service
```

## Flags

```
-c <config_path>, --config <config_path>: specify a config path, by default
                                          set to ${XDG_CONFIG_HOME}/hypr/hypridle.conf
-q, --quiet
-v, --verbose
```
07070100000009000081A400000000000000000000000167E6AF6200000006000000000000000000000000000000000000001700000000hypridle-0.1.6/VERSION0.1.6
0707010000000A000041ED00000000000000000000000267E6AF6200000000000000000000000000000000000000000000001600000000hypridle-0.1.6/assets0707010000000B000081A400000000000000000000000167E6AF6200000639000000000000000000000000000000000000002300000000hypridle-0.1.6/assets/example.conf# sample hypridle.conf
# for more configuration options, refer https://wiki.hyprland.org/Hypr-Ecosystem/hypridle

general {
    lock_cmd = pidof hyprlock || hyprlock       # avoid starting multiple hyprlock instances.
    before_sleep_cmd = loginctl lock-session    # lock before suspend.
    after_sleep_cmd = hyprctl dispatch dpms on  # to avoid having to press a key twice to turn on the display.
}

listener {
    timeout = 150                                # 2.5min.
    on-timeout = brightnessctl -s set 10         # set monitor backlight to minimum, avoid 0 on OLED monitor.
    on-resume = brightnessctl -r                 # monitor backlight restore.
}

# 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.
}
0707010000000C000081A400000000000000000000000167E6AF6200000E01000000000000000000000000000000000000001A00000000hypridle-0.1.6/flake.lock{
  "nodes": {
    "hyprland-protocols": {
      "inputs": {
        "nixpkgs": [
          "nixpkgs"
        ],
        "systems": [
          "systems"
        ]
      },
      "locked": {
        "lastModified": 1737556638,
        "narHash": "sha256-laKgI3mr2qz6tas/q3tuGPxMdsGhBi/w+HO+hO2f1AY=",
        "owner": "hyprwm",
        "repo": "hyprland-protocols",
        "rev": "4c75dd5c015c8a0e5a34c6d02a018a650f57feb5",
        "type": "github"
      },
      "original": {
        "owner": "hyprwm",
        "repo": "hyprland-protocols",
        "type": "github"
      }
    },
    "hyprlang": {
      "inputs": {
        "hyprutils": [
          "hyprutils"
        ],
        "nixpkgs": [
          "nixpkgs"
        ],
        "systems": [
          "systems"
        ]
      },
      "locked": {
        "lastModified": 1734364628,
        "narHash": "sha256-ii8fzJfI953n/EmIxVvq64ZAwhvwuuPHWfGd61/mJG8=",
        "lastModified": 1737634606,
        "narHash": "sha256-W7W87Cv6wqZ9PHegI6rH1+ve3zJPiyevMFf0/HwdbCQ=",
        "owner": "hyprwm",
        "repo": "hyprlang",
        "rev": "f41271d35cc0f370d300413d756c2677f386af9d",
        "type": "github"
      },
      "original": {
        "owner": "hyprwm",
        "repo": "hyprlang",
        "type": "github"
      }
    },
    "hyprutils": {
      "inputs": {
        "nixpkgs": [
          "nixpkgs"
        ],
        "systems": [
          "systems"
        ]
      },
      "locked": {
        "lastModified": 1737632363,
        "narHash": "sha256-X9I8POSlHxBVjD0fiX1O2j7U9Zi1+4rIkrsyHP0uHXY=",
        "owner": "hyprwm",
        "repo": "hyprutils",
        "rev": "006620eb29d54ea9086538891404c78563d1bae1",
        "type": "github"
      },
      "original": {
        "owner": "hyprwm",
        "repo": "hyprutils",
        "type": "github"
      }
    },
    "hyprwayland-scanner": {
      "inputs": {
        "nixpkgs": [
          "nixpkgs"
        ],
        "systems": [
          "systems"
        ]
      },
      "locked": {
        "lastModified": 1735493474,
        "narHash": "sha256-fktzv4NaqKm94VAkAoVqO/nqQlw+X0/tJJNAeCSfzK4=",
        "owner": "hyprwm",
        "repo": "hyprwayland-scanner",
        "rev": "de913476b59ee88685fdc018e77b8f6637a2ae0b",
        "type": "github"
      },
      "original": {
        "owner": "hyprwm",
        "repo": "hyprwayland-scanner",
        "type": "github"
      }
    },
    "nixpkgs": {
      "locked": {
        "lastModified": 1737469691,
        "narHash": "sha256-nmKOgAU48S41dTPIXAq0AHZSehWUn6ZPrUKijHAMmIk=",
        "owner": "NixOS",
        "repo": "nixpkgs",
        "rev": "9e4d5190a9482a1fb9d18adf0bdb83c6e506eaab",
        "type": "github"
      },
      "original": {
        "owner": "NixOS",
        "ref": "nixos-unstable",
        "repo": "nixpkgs",
        "type": "github"
      }
    },
    "root": {
      "inputs": {
        "hyprland-protocols": "hyprland-protocols",
        "hyprlang": "hyprlang",
        "hyprutils": "hyprutils",
        "hyprwayland-scanner": "hyprwayland-scanner",
        "nixpkgs": "nixpkgs",
        "systems": "systems"
      }
    },
    "systems": {
      "locked": {
        "lastModified": 1689347949,
        "narHash": "sha256-12tWmuL2zgBgZkdoB6qXZsgJEH9LR3oUgpaQq2RbI80=",
        "owner": "nix-systems",
        "repo": "default-linux",
        "rev": "31732fcf5e8fea42e59c2488ad31a0e651500f68",
        "type": "github"
      },
      "original": {
        "owner": "nix-systems",
        "repo": "default-linux",
        "type": "github"
      }
    }
  },
  "root": "root",
  "version": 7
}
0707010000000D000081A400000000000000000000000167E6AF62000006B3000000000000000000000000000000000000001900000000hypridle-0.1.6/flake.nix{
  description = "Hyprland's idle daemon";

  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
    systems.url = "github:nix-systems/default-linux";

    hyprlang = {
      url = "github:hyprwm/hyprlang";
      inputs.nixpkgs.follows = "nixpkgs";
      inputs.systems.follows = "systems";
      inputs.hyprutils.follows = "hyprutils";
    };

    hyprutils = {
      url = "github:hyprwm/hyprutils";
      inputs.nixpkgs.follows = "nixpkgs";
      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 = {
    self,
    nixpkgs,
    systems,
    ...
  } @ inputs: let
    inherit (nixpkgs) lib;
    eachSystem = lib.genAttrs (import systems);

    pkgsFor = eachSystem (system:
      import nixpkgs {
        localSystem.system = system;
        overlays = with self.overlays; [default];
      });
  in {
    overlays = import ./nix/overlays.nix {inherit inputs lib;};

    packages = eachSystem (system: {
      default = self.packages.${system}.hypridle;
      inherit (pkgsFor.${system}) hypridle;
    });

    homeManagerModules = {
      default = self.homeManagerModules.hypridle;
      hypridle = builtins.throw "hypridle: the flake HM module has been removed. Use the module from Home Manager upstream.";
    };

    checks = eachSystem (system: self.packages.${system});

    formatter = eachSystem (system: pkgsFor.${system}.alejandra);
  };
}
0707010000000E000041ED00000000000000000000000267E6AF6200000000000000000000000000000000000000000000001300000000hypridle-0.1.6/nix0707010000000F000081A400000000000000000000000167E6AF62000002EF000000000000000000000000000000000000001F00000000hypridle-0.1.6/nix/default.nix{
  cmake,
  hyprland-protocols,
  hyprlang,
  hyprutils,
  hyprwayland-scanner,
  lib,
  pkg-config,
  sdbus-cpp,
  stdenv,
  systemd,
  wayland,
  wayland-protocols,
  wayland-scanner,
  version ? "git",
}:
stdenv.mkDerivation {
  pname = "hypridle";
  inherit version;
  src = ../.;

  nativeBuildInputs = [
    cmake
    hyprwayland-scanner
    pkg-config
    wayland-scanner
  ];

  buildInputs = [
    hyprland-protocols
    hyprlang
    hyprutils
    sdbus-cpp
    systemd
    wayland
    wayland-protocols
  ];

  meta = {
    homepage = "https://github.com/hyprwm/hypridle";
    description = "An idle management daemon for Hyprland";
    license = lib.licenses.bsd3;
    platforms = lib.platforms.linux;
    mainProgram = "hypridle";
  };
}
07070100000010000081A400000000000000000000000167E6AF62000004B3000000000000000000000000000000000000002000000000hypridle-0.1.6/nix/overlays.nix{
  lib,
  inputs,
}: let
  mkDate = longDate: (lib.concatStringsSep "-" [
    (builtins.substring 0 4 longDate)
    (builtins.substring 4 2 longDate)
    (builtins.substring 6 2 longDate)
  ]);

  version = lib.removeSuffix "\n" (builtins.readFile ../VERSION);
in {
  default = inputs.self.overlays.hypridle;

  hypridle = lib.composeManyExtensions [
    inputs.hyprland-protocols.overlays.default
    inputs.hyprlang.overlays.default
    inputs.hyprutils.overlays.default
    inputs.hyprwayland-scanner.overlays.default
    inputs.self.overlays.sdbuscpp
    (final: prev: {
      hypridle = prev.callPackage ./default.nix {
        stdenv = prev.gcc14Stdenv;
        version = version + "+date=" + (mkDate (inputs.self.lastModifiedDate or "19700101")) + "_" + (inputs.self.shortRev or "dirty");
        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=";
      };
    });
  };
}
07070100000011000041ED00000000000000000000000267E6AF6200000000000000000000000000000000000000000000001300000000hypridle-0.1.6/src07070100000012000041ED00000000000000000000000267E6AF6200000000000000000000000000000000000000000000001A00000000hypridle-0.1.6/src/config07070100000013000081A400000000000000000000000167E6AF6200000CCC000000000000000000000000000000000000002C00000000hypridle-0.1.6/src/config/ConfigManager.cpp#include "ConfigManager.hpp"
#include <hyprutils/path/Path.hpp>
#include <filesystem>

static std::string getMainConfigPath() {
    static const auto paths = Hyprutils::Path::findConfig("hypridle");
    if (paths.first.has_value())
        return paths.first.value();
    else
        throw std::runtime_error("Could not find config in HOME, XDG_CONFIG_HOME, XDG_CONFIG_DIRS or /etc/hypr.");
}

CConfigManager::CConfigManager(std::string configPath) :
    m_config(configPath.empty() ? getMainConfigPath().c_str() : configPath.c_str(), Hyprlang::SConfigOptions{.throwAllErrors = true, .allowMissingConfig = false}) {
    ;
}

void CConfigManager::init() {
    m_config.addSpecialCategory("listener", Hyprlang::SSpecialCategoryOptions{.key = nullptr, .anonymousKeyBased = true});
    m_config.addSpecialConfigValue("listener", "timeout", Hyprlang::INT{-1});
    m_config.addSpecialConfigValue("listener", "on-timeout", Hyprlang::STRING{""});
    m_config.addSpecialConfigValue("listener", "on-resume", Hyprlang::STRING{""});

    m_config.addConfigValue("general:lock_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:after_sleep_cmd", Hyprlang::STRING{""});
    m_config.addConfigValue("general:ignore_dbus_inhibit", Hyprlang::INT{0});
    m_config.addConfigValue("general:ignore_systemd_inhibit", Hyprlang::INT{0});
    m_config.addConfigValue("general:inhibit_sleep", Hyprlang::INT{2});

    m_config.commence();

    auto result = m_config.parse();

    if (result.error)
        Debug::log(ERR, "Config has errors:\n{}\nProceeding ignoring faulty entries", result.getError());

    result = postParse();

    if (result.error)
        Debug::log(ERR, "Config has errors:\n{}\nProceeding ignoring faulty entries", result.getError());
}

Hyprlang::CParseResult CConfigManager::postParse() {
    const auto             KEYS = m_config.listKeysForSpecialCategory("listener");

    Hyprlang::CParseResult result;
    if (KEYS.empty()) {
        result.setError("No rules configured");
        return result;
    }

    for (auto& k : KEYS) {
        STimeoutRule  rule;

        Hyprlang::INT timeout = std::any_cast<Hyprlang::INT>(m_config.getSpecialConfigValue("listener", "timeout", k.c_str()));

        rule.timeout   = timeout;
        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()));

        if (timeout == -1) {
            result.setError("Category has a missing timeout setting");
            continue;
        }

        m_vRules.emplace_back(rule);
    }

    for (auto& r : m_vRules) {
        Debug::log(LOG, "Registered timeout rule for {}s:\n      on-timeout: {}\n      on-resume: {}", r.timeout, r.onTimeout, r.onResume);
    }

    return result;
}

std::vector<CConfigManager::STimeoutRule> CConfigManager::getRules() {
    return m_vRules;
}
07070100000014000081A400000000000000000000000167E6AF62000002F9000000000000000000000000000000000000002C00000000hypridle-0.1.6/src/config/ConfigManager.hpp#pragma once

#include "../helpers/Log.hpp"

#include <hyprlang.hpp>

#include <vector>
#include <memory>

class CConfigManager {
  public:
    CConfigManager(std::string configPath);
    void init();

    struct STimeoutRule {
        uint64_t    timeout   = 0;
        std::string onTimeout = "";
        std::string onResume  = "";
    };

    std::vector<STimeoutRule> getRules();

    template <typename T>
    Hyprlang::CSimpleConfigValue<T> getValue(const std::string& name) {
        return Hyprlang::CSimpleConfigValue<T>(&m_config, name.c_str());
    }

  private:
    Hyprlang::CConfig         m_config;

    std::vector<STimeoutRule> m_vRules;

    Hyprlang::CParseResult    postParse();
};

inline std::unique_ptr<CConfigManager> g_pConfigManager;
07070100000015000041ED00000000000000000000000267E6AF6200000000000000000000000000000000000000000000001800000000hypridle-0.1.6/src/core07070100000016000081A400000000000000000000000167E6AF6200005FC4000000000000000000000000000000000000002500000000hypridle-0.1.6/src/core/Hypridle.cpp#include "Hypridle.hpp"
#include "../helpers/Log.hpp"
#include "../config/ConfigManager.hpp"
#include "csignal"
#include <sys/wait.h>
#include <sys/poll.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
#include <algorithm>
#include <thread>
#include <mutex>
#include <hyprutils/os/Process.hpp>

CHypridle::CHypridle() {
    m_sWaylandState.display = wl_display_connect(nullptr);
    if (!m_sWaylandState.display) {
        Debug::log(CRIT, "Couldn't connect to a wayland compositor");
        exit(1);
    }
}

void CHypridle::run() {
    m_sWaylandState.registry = makeShared<CCWlRegistry>((wl_proxy*)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) {
            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);

    if (!m_sWaylandIdleState.notifier) {
        Debug::log(CRIT, "Couldn't bind to ext-idle-notifier-v1, does your compositor support it?");
        exit(1);
    }

    const auto RULES = g_pConfigManager->getRules();
    m_sWaylandIdleState.listeners.resize(RULES.size());

    Debug::log(LOG, "found {} rules", RULES.size());

    for (size_t i = 0; i < RULES.size(); ++i) {
        auto&       l = m_sWaylandIdleState.listeners[i];
        const auto& r = RULES[i];
        l.onRestore   = r.onResume;
        l.onTimeout   = r.onTimeout;

        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);

    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");

    try {
        m_sDBUSState.connection = sdbus::createSystemBusConnection();
    } catch (std::exception& e) {
        Debug::log(CRIT, "Couldn't create the dbus connection ({})", e.what());
        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();
    if (m_inhibitSleepBehavior != SLEEP_INHIBIT_NONE)
        inhibitSleep();
    enterEventLoop();
}

void CHypridle::enterEventLoop() {

    nfds_t pollfdsCount = m_sDBUSState.screenSaverServiceConnection ? 3 : 2;

    pollfd pollfds[] = {
        {
            .fd     = m_sDBUSState.connection->getEventLoopPollData().fd,
            .events = POLLIN,
        },
        {
            .fd     = wl_display_get_fd(m_sWaylandState.display),
            .events = POLLIN,
        },
        {
            .fd     = m_sDBUSState.screenSaverServiceConnection ? m_sDBUSState.screenSaverServiceConnection->getEventLoopPollData().fd : 0,
            .events = POLLIN,
        },
    };

    std::thread pollThr([this, &pollfds, &pollfdsCount]() {
        while (1) {
            int ret = poll(pollfds, pollfdsCount, 5000 /* 5 seconds, reasonable. It's because we might need to terminate */);
            if (ret < 0) {
                Debug::log(CRIT, "[core] Polling fds failed with {}", errno);
                m_bTerminate = true;
                exit(1);
            }

            for (size_t i = 0; i < pollfdsCount; ++i) {
                if (pollfds[i].revents & POLLHUP) {
                    Debug::log(CRIT, "[core] Disconnected from pollfd id {}", i);
                    m_bTerminate = true;
                    exit(1);
                }
            }

            if (m_bTerminate)
                break;

            if (ret != 0) {
                Debug::log(TRACE, "[core] got poll event");
                std::lock_guard<std::mutex> lg(m_sEventLoopInternals.loopRequestMutex);
                m_sEventLoopInternals.shouldProcess = true;
                m_sEventLoopInternals.loopSignal.notify_all();
            }
        }
    });

    while (1) { // dbus events
        // wait for being awakened
        m_sEventLoopInternals.loopRequestMutex.unlock(); // unlock, we are ready to take events

        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
            m_sEventLoopInternals.loopSignal.wait(lk, [this] { return m_sEventLoopInternals.shouldProcess == true; }); // wait for events

        m_sEventLoopInternals.loopRequestMutex.lock(); // lock incoming events

        if (m_bTerminate)
            break;

        m_sEventLoopInternals.shouldProcess = false;

        std::lock_guard<std::mutex> lg(m_sEventLoopInternals.eventLock);

        if (pollfds[0].revents & POLLIN /* dbus */) {
            Debug::log(TRACE, "got dbus event");
            while (m_sDBUSState.connection->processPendingEvent()) {
                ;
            }
        }

        if (pollfds[1].revents & POLLIN /* wl */) {
            Debug::log(TRACE, "got wl event");
            wl_display_flush(m_sWaylandState.display);
            if (wl_display_prepare_read(m_sWaylandState.display) == 0) {
                wl_display_read_events(m_sWaylandState.display);
                wl_display_dispatch_pending(m_sWaylandState.display);
            } else {
                wl_display_dispatch(m_sWaylandState.display);
            }
        }

        if (pollfdsCount > 2 && pollfds[2].revents & POLLIN /* dbus2 */) {
            Debug::log(TRACE, "got dbus event");
            while (m_sDBUSState.screenSaverServiceConnection->processPendingEvent()) {
                ;
            }
        }

        // finalize wayland dispatching. Dispatch pending on the queue
        int ret = 0;
        do {
            ret = wl_display_dispatch_pending(m_sWaylandState.display);
            wl_display_flush(m_sWaylandState.display);
        } while (ret > 0);
    }

    Debug::log(ERR, "[core] Terminated");
}

static void spawn(const std::string& args) {
    Debug::log(LOG, "Executing {}", args);

    Hyprutils::OS::CProcess proc("/bin/sh", {"-c", args});
    if (!proc.runAsync()) {
        Debug::log(ERR, "Failed run \"{}\"", args);
        return;
    }

    Debug::log(LOG, "Process Created with pid {}", proc.pid());
}

void CHypridle::onIdled(SIdleListener* pListener) {
    Debug::log(LOG, "Idled: rule {:x}", (uintptr_t)pListener);
    isIdled = true;
    if (g_pHypridle->m_iInhibitLocks > 0) {
        Debug::log(LOG, "Ignoring from onIdled(), inhibit locks: {}", g_pHypridle->m_iInhibitLocks);
        return;
    }

    if (pListener->onTimeout.empty()) {
        Debug::log(LOG, "Ignoring, onTimeout is empty.");
        return;
    }

    Debug::log(LOG, "Running {}", pListener->onTimeout);
    spawn(pListener->onTimeout);
}

void CHypridle::onResumed(SIdleListener* pListener) {
    Debug::log(LOG, "Resumed: rule {:x}", (uintptr_t)pListener);
    isIdled = false;
    if (g_pHypridle->m_iInhibitLocks > 0) {
        Debug::log(LOG, "Ignoring from onResumed(), inhibit locks: {}", g_pHypridle->m_iInhibitLocks);
        return;
    }

    if (pListener->onRestore.empty()) {
        Debug::log(LOG, "Ignoring, onRestore is empty.");
        return;
    }

    Debug::log(LOG, "Running {}", pListener->onRestore);
    spawn(pListener->onRestore);
}

void CHypridle::onInhibit(bool lock) {
    m_iInhibitLocks += lock ? 1 : -1;

    if (m_iInhibitLocks < 0) {
        Debug::log(WARN, "BUG THIS: inhibit locks < 0: {}", m_iInhibitLocks);
        m_iInhibitLocks = 0;
    }

    if (m_iInhibitLocks == 0 && isIdled) {
        const auto RULES = g_pConfigManager->getRules();

        for (size_t i = 0; i < RULES.size(); ++i) {
            auto&       l = m_sWaylandIdleState.listeners[i];
            const auto& r = RULES[i];

            l.notification->sendDestroy();

            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()); });
        }
    }

    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 (*LOCKCMD)
        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 (*UNLOCKCMD)
        spawn(*UNLOCKCMD);
}

CHypridle::SDbusInhibitCookie CHypridle::getDbusInhibitCookie(uint32_t cookie) {
    for (auto& c : m_sDBUSState.inhibitCookies) {
        if (c.cookie == cookie)
            return c;
    }

    return {};
}

void CHypridle::registerDbusInhibitCookie(CHypridle::SDbusInhibitCookie& cookie) {
    m_sDBUSState.inhibitCookies.push_back(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; });

    if (IT == m_sDBUSState.inhibitCookies.end())
        return false;

    m_sDBUSState.inhibitCookies.erase(IT);
    return true;
}

bool CHypridle::unregisterDbusInhibitCookies(const std::string& 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) {
    // lock & unlock
    static const auto LOCKCMD   = g_pConfigManager->getValue<Hyprlang::STRING>("general:lock_cmd");
    static const auto UNLOCKCMD = g_pConfigManager->getValue<Hyprlang::STRING>("general:unlock_cmd");

    Debug::log(LOG, "Got dbus .Session");

    const std::string MEMBER = msg.getMemberName();
    if (MEMBER == "Lock") {
        Debug::log(LOG, "Got Lock from dbus");

        if (!std::string{*LOCKCMD}.empty()) {
            Debug::log(LOG, "Locking with {}", *LOCKCMD);
            spawn(*LOCKCMD);
        }
    } else if (MEMBER == "Unlock") {
        Debug::log(LOG, "Got Unlock from dbus");

        if (!std::string{*UNLOCKCMD}.empty()) {
            Debug::log(LOG, "Unlocking with {}", *UNLOCKCMD);
            spawn(*UNLOCKCMD);
        }
    }
}

static void handleDbusSleep(sdbus::Message msg) {
    const std::string MEMBER = msg.getMemberName();

    if (MEMBER != "PrepareForSleep")
        return;

    bool toSleep = true;
    msg >> toSleep;

    static const auto SLEEPCMD      = g_pConfigManager->getValue<Hyprlang::STRING>("general:before_sleep_cmd");
    static const auto AFTERSLEEPCMD = g_pConfigManager->getValue<Hyprlang::STRING>("general:after_sleep_cmd");

    Debug::log(LOG, "Got PrepareForSleep from dbus with sleep {}", toSleep);

    std::string cmd = toSleep ? *SLEEPCMD : *AFTERSLEEPCMD;

    if (!toSleep)
        g_pHypridle->handleInhibitOnDbusSleep(toSleep);

    if (!cmd.empty())
        spawn(cmd);

    if (toSleep)
        g_pHypridle->handleInhibitOnDbusSleep(toSleep);
}

static void handleDbusBlockInhibits(const std::string& inhibits) {
    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
    auto inhibits_ = ":" + inhibits + ":";
    if (inhibits_.contains(":idle:")) {
        if (!inhibited) {
            inhibited = true;
            Debug::log(LOG, "systemd idle inhibit active");
            g_pHypridle->onInhibit(true);
        }
    } else if (inhibited) {
        inhibited = false;
        Debug::log(LOG, "systemd idle inhibit inactive");
        g_pHypridle->onInhibit(false);
    }
}

static void handleDbusBlockInhibitsPropertyChanged(sdbus::Message msg) {
    std::string                           interface;
    std::map<std::string, sdbus::Variant> changedProperties;
    msg >> interface >> changedProperties;
    if (changedProperties.contains("BlockInhibited")) {
        handleDbusBlockInhibits(changedProperties["BlockInhibited"].get<std::string>());
    }
}

static uint32_t handleDbusScreensaver(std::string app, std::string reason, uint32_t cookie, bool inhibit, const char* sender) {
    std::string ownerID = sender;

    if (!inhibit) {
        Debug::log(TRACE, "Read uninhibit cookie: {}", cookie);
        const auto COOKIE = g_pHypridle->getDbusInhibitCookie(cookie);
        if (COOKIE.cookie == 0) {
            Debug::log(WARN, "No cookie in uninhibit");
        } else {
            app     = COOKIE.app;
            reason  = COOKIE.reason;
            ownerID = COOKIE.ownerID;

            if (!g_pHypridle->unregisterDbusInhibitCookie(COOKIE))
                Debug::log(WARN, "BUG THIS: attempted to unregister unknown cookie");
        }
    }

    Debug::log(LOG, "ScreenSaver inhibit: {} dbus message from {} (owner: {}) with content {}", inhibit, app, ownerID, reason);

    if (inhibit)
        g_pHypridle->onInhibit(true);
    else
        g_pHypridle->onInhibit(false);

    static uint32_t cookieID = 1337;

    if (inhibit) {
        auto cookie = CHypridle::SDbusInhibitCookie{.cookie = cookieID, .app = app, .reason = reason, .ownerID = ownerID};

        Debug::log(LOG, "Cookie {} sent", cookieID);

        g_pHypridle->registerDbusInhibitCookie(cookie);

        return cookieID++;
    }

    return 0;
}

static void handleDbusNameOwnerChanged(sdbus::Message msg) {
    std::string name, oldOwner, newOwner;
    msg >> name >> oldOwner >> newOwner;

    if (!newOwner.empty())
        return;

    if (g_pHypridle->unregisterDbusInhibitCookies(oldOwner)) {
        Debug::log(LOG, "App with owner {} disconnected", oldOwner);
        g_pHypridle->onInhibit(false);
    }
}

void CHypridle::setupDBUS() {
    static const auto IGNOREDBUSINHIBIT    = g_pConfigManager->getValue<Hyprlang::INT>("general:ignore_dbus_inhibit");
    static const auto IGNORESYSTEMDINHIBIT = g_pConfigManager->getValue<Hyprlang::INT>("general:ignore_systemd_inhibit");

    auto              systemConnection = sdbus::createSystemBusConnection();
    auto              proxy            = sdbus::createProxy(*systemConnection, sdbus::ServiceName{"org.freedesktop.login1"}, sdbus::ObjectPath{"/org/freedesktop/login1"});
    sdbus::ObjectPath path;

    try {
        proxy->callMethod("GetSession").onInterface("org.freedesktop.login1.Manager").withArguments(std::string{"auto"}).storeResultsTo(path);

        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.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()); }

    Debug::log(LOG, "Using dbus path {}", path.c_str());

    if (!*IGNORESYSTEMDINHIBIT) {
        m_sDBUSState.connection->addMatch("type='signal',path='/org/freedesktop/login1',interface='org.freedesktop.DBus.Properties'", ::handleDbusBlockInhibitsPropertyChanged);

        try {
            std::string value = (proxy->getProperty("BlockInhibited").onInterface("org.freedesktop.login1.Manager")).get<std::string>();
            handleDbusBlockInhibits(value);
        } catch (std::exception& e) { Debug::log(WARN, "Couldn't retrieve current systemd inhibits ({})", e.what()); }
    }

    if (!*IGNOREDBUSINHIBIT) {
        // attempt to register as ScreenSaver
        std::string paths[] = {
            "/org/freedesktop/ScreenSaver",
            "/ScreenSaver",
        };

        try {
            m_sDBUSState.screenSaverServiceConnection = sdbus::createSessionBusConnection(sdbus::ServiceName{"org.freedesktop.ScreenSaver"});

            for (const std::string& path : paths) {
                try {
                    auto obj = sdbus::createObject(*m_sDBUSState.screenSaverServiceConnection, sdbus::ObjectPath{path});

                    obj->addVTable(sdbus::registerMethod("Inhibit").implementedAs([object = obj.get()](std::string s1, std::string s2) {
                           return handleDbusScreensaver(s1, s2, 0, true, object->getCurrentlyProcessedMessage().getSender());
                       }),
                                   sdbus::registerMethod("UnInhibit").implementedAs([object = obj.get()](uint32_t c) {
                                       handleDbusScreensaver("", "", c, false, object->getCurrentlyProcessedMessage().getSender());
                                   }))
                        .forInterface(sdbus::InterfaceName{"org.freedesktop.ScreenSaver"});

                    m_sDBUSState.screenSaverObjects.push_back(std::move(obj));
                } catch (std::exception& e) { Debug::log(ERR, "Failed registering for {}, perhaps taken?\nerr: {}", path, e.what()); }
            }

            m_sDBUSState.screenSaverServiceConnection->addMatch("type='signal',sender='org.freedesktop.DBus',interface='org.freedesktop.DBus',member='NameOwnerChanged'",
                                                                ::handleDbusNameOwnerChanged);
        } catch (std::exception& e) { Debug::log(ERR, "Couldn't connect to session dbus\nerr: {}", e.what()); }
    }

    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.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();
}
07070100000017000081A400000000000000000000000167E6AF6200000C9D000000000000000000000000000000000000002500000000hypridle-0.1.6/src/core/Hypridle.hpp#pragma once

#include <memory>
#include <vector>
#include <sdbus-c++/sdbus-c++.h>
#include <hyprutils/os/FileDescriptor.hpp>
#include <condition_variable>

#include "wayland.hpp"
#include "ext-idle-notify-v1.hpp"
#include "hyprland-lock-notify-v1.hpp"

#include "../defines.hpp"

class CHypridle {
  public:
    CHypridle();

    struct SIdleListener {
        SP<CCExtIdleNotificationV1> notification = nullptr;
        std::string                 onTimeout    = "";
        std::string                 onRestore    = "";
    };

    struct SDbusInhibitCookie {
        uint32_t    cookie = 0;
        std::string app, reason, ownerID;
    };

    void               run();

    void               onGlobal(void* data, struct wl_registry* registry, uint32_t name, const char* interface, uint32_t version);
    void               onGlobalRemoved(void* data, struct wl_registry* registry, uint32_t name);

    void               onIdled(SIdleListener*);
    void               onResumed(SIdleListener*);

    void               onInhibit(bool lock);

    void               onLocked();
    void               onUnlocked();

    SDbusInhibitCookie getDbusInhibitCookie(uint32_t cookie);
    void               registerDbusInhibitCookie(SDbusInhibitCookie& cookie);
    bool               unregisterDbusInhibitCookie(const SDbusInhibitCookie& cookie);
    bool               unregisterDbusInhibitCookies(const std::string& ownerID);

    void               handleInhibitOnDbusSleep(bool toSleep);
    void               inhibitSleep();
    void               uninhibitSleep();

  private:
    void    setupDBUS();
    void    enterEventLoop();

    bool    m_bTerminate    = false;
    bool    isIdled         = false;
    bool    m_isLocked      = false;
    int64_t m_iInhibitLocks = 0;

    enum {
        SLEEP_INHIBIT_NONE,
        SLEEP_INHIBIT_NORMAL,
        SLEEP_INHIBIT_LOCK_NOTIFY,
    } m_inhibitSleepBehavior;

    struct {
        wl_display*                      display          = nullptr;
        SP<CCWlRegistry>                 registry         = nullptr;
        SP<CCWlSeat>                     seat             = nullptr;
        SP<CCHyprlandLockNotifierV1>     lockNotifier     = nullptr;
        SP<CCHyprlandLockNotificationV1> lockNotification = nullptr;
    } m_sWaylandState;

    struct {
        SP<CCExtIdleNotifierV1>    notifier = nullptr;

        std::vector<SIdleListener> listeners;
    } m_sWaylandIdleState;

    struct {
        std::unique_ptr<sdbus::IConnection>          connection;
        std::unique_ptr<sdbus::IConnection>          screenSaverServiceConnection;
        std::unique_ptr<sdbus::IProxy>               login;
        std::vector<std::unique_ptr<sdbus::IObject>> screenSaverObjects;
        std::vector<SDbusInhibitCookie>              inhibitCookies;
        Hyprutils::OS::CFileDescriptor               sleepInhibitFd;
    } m_sDBUSState;

    struct {
        std::condition_variable loopSignal;
        std::mutex              loopMutex;
        std::atomic<bool>       shouldProcess = false;
        std::mutex              loopRequestMutex;
        std::mutex              eventLock;
    } m_sEventLoopInternals;
};

inline std::unique_ptr<CHypridle> g_pHypridle;
07070100000018000081A400000000000000000000000167E6AF62000000DE000000000000000000000000000000000000001F00000000hypridle-0.1.6/src/defines.hpp#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
07070100000019000041ED00000000000000000000000267E6AF6200000000000000000000000000000000000000000000001B00000000hypridle-0.1.6/src/helpers0707010000001A000081A400000000000000000000000167E6AF6200000944000000000000000000000000000000000000002300000000hypridle-0.1.6/src/helpers/Log.hpp#pragma once
#include <format>
#include <iostream>
#include <string>

enum eLogLevel {
    TRACE = 0,
    INFO,
    LOG,
    WARN,
    ERR,
    CRIT,
    NONE
};

#define RASSERT(expr, reason, ...)                                                                                                                                                 \
    if (!(expr)) {                                                                                                                                                                 \
        Debug::log(CRIT, "\n==========================================================================================\nASSERTION FAILED! \n\n{}\n\nat: line {} in {}",            \
                   std::format(reason, ##__VA_ARGS__), __LINE__,                                                                                                                   \
                   ([]() constexpr -> std::string { return std::string(__FILE__).substr(std::string(__FILE__).find_last_of('/') + 1); })().c_str());                               \
        printf("Assertion failed! See the log in /tmp/hypr/hyprland.log for more info.");                                                                                          \
        *((int*)nullptr) = 1; /* so that we crash and get a coredump */                                                                                                            \
    }

#define ASSERT(expr) RASSERT(expr, "?")

namespace Debug {
    inline bool quiet   = false;
    inline bool verbose = false;

    template <typename... Args>
    void log(eLogLevel level, const std::string& fmt, Args&&... args) {

        if (!verbose && level == TRACE)
            return;

        if (quiet)
            return;

        if (level != NONE) {
            std::cout << '[';

            switch (level) {
                case TRACE: std::cout << "TRACE"; break;
                case INFO: std::cout << "INFO"; break;
                case LOG: std::cout << "LOG"; break;
                case WARN: std::cout << "WARN"; break;
                case ERR: std::cout << "ERR"; break;
                case CRIT: std::cout << "CRITICAL"; break;
                default: break;
            }

            std::cout << "] ";
        }

        std::cout << std::vformat(fmt, std::make_format_args(args...)) << std::endl;
    }
};0707010000001B000081A400000000000000000000000167E6AF62000006A7000000000000000000000000000000000000001C00000000hypridle-0.1.6/src/main.cpp
#include "config/ConfigManager.hpp"
#include "core/Hypridle.hpp"
#include "helpers/Log.hpp"

int main(int argc, char** argv, char** envp) {
    std::string configPath;

    for (int i = 1; i < argc; ++i) {
        std::string arg = argv[i];

        if (arg == "--verbose" || arg == "-v")
            Debug::verbose = true;

        else if (arg == "--quiet" || arg == "-q")
            Debug::quiet = true;

        else if (arg == "--version" || arg == "-V") {
            Debug::log(NONE, "hypridle v{}", HYPRIDLE_VERSION);
            return 0;
        }

        else if (arg == "--config" || arg == "-c") {
            if (i + 1 >= argc) {
                Debug::log(NONE, "After " + arg + " you should provide a path to a config file.");
                return 1;
            }

            if (!configPath.empty()) {
                Debug::log(NONE, "Multiple config files are provided.");
                return 1;
            }

            configPath = argv[++i];
            if (configPath[0] == '-') { // Should be fine, because of the null terminator
                Debug::log(NONE, "After " + arg + " you should provide a path to a config file.");
                return 1;
            }
        }
    }

    try {
        g_pConfigManager = std::make_unique<CConfigManager>(configPath);
        g_pConfigManager->init();
    } catch (const char* err) {
        Debug::log(CRIT, "ConfigManager threw: {}", err);
        std::string strerr = err;
        if (strerr.contains("File does not exist"))
            Debug::log(NONE, "           Make sure you have a config.");
        return 1;
    }

    g_pHypridle = std::make_unique<CHypridle>();
    g_pHypridle->run();

    return 0;
}
0707010000001C000041ED00000000000000000000000267E6AF6200000000000000000000000000000000000000000000001700000000hypridle-0.1.6/systemd0707010000001D000081A400000000000000000000000167E6AF6200000153000000000000000000000000000000000000002B00000000hypridle-0.1.6/systemd/hypridle.service.in[Unit]
Description=Hyprland's idle daemon
Documentation=https://wiki.hyprland.org/Hypr-Ecosystem/hypridle
PartOf=graphical-session.target
After=graphical-session.target
ConditionEnvironment=WAYLAND_DISPLAY

[Service]
Type=simple
ExecStart=@CMAKE_INSTALL_PREFIX@/bin/hypridle
Restart=on-failure

[Install]
WantedBy=graphical-session.target
07070100000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000B00000000TRAILER!!!124 blocks
openSUSE Build Service is sponsored by