mirror of
https://github.com/hyprwm/hypridle.git
synced 2024-11-16 15:15:59 +01:00
core: initial commit
This commit is contained in:
parent
c651d3cc02
commit
9e8d11a964
11 changed files with 645 additions and 0 deletions
65
.clang-format
Normal file
65
.clang-format
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
---
|
||||||
|
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
|
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
.vscode/
|
||||||
|
build/
|
||||||
|
protocols/
|
75
CMakeLists.txt
Normal file
75
CMakeLists.txt
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
cmake_minimum_required(VERSION 3.19)
|
||||||
|
|
||||||
|
set(VERSION 0.1)
|
||||||
|
|
||||||
|
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()
|
||||||
|
|
||||||
|
include_directories(
|
||||||
|
.
|
||||||
|
"protocols/"
|
||||||
|
)
|
||||||
|
|
||||||
|
# configure
|
||||||
|
set(CMAKE_CXX_STANDARD 23)
|
||||||
|
add_compile_options(-Wall -Wextra -Wno-unused-parameter -Wno-unused-value
|
||||||
|
-Wno-missing-field-initializers -Wno-narrowing)
|
||||||
|
|
||||||
|
# dependencies
|
||||||
|
message(STATUS "Checking deps...")
|
||||||
|
|
||||||
|
find_package(Threads REQUIRED)
|
||||||
|
find_package(PkgConfig REQUIRED)
|
||||||
|
pkg_check_modules(deps REQUIRED IMPORTED_TARGET wayland-client wayland-protocols hyprlang>=0.3.2 sdbus-c++ tomlplusplus)
|
||||||
|
|
||||||
|
file(GLOB_RECURSE SRCFILES CONFIGURE_DEPENDS "src/*.cpp")
|
||||||
|
add_executable(hypridle ${SRCFILES})
|
||||||
|
target_link_libraries(hypridle PRIVATE rt Threads::Threads PkgConfig::deps)
|
||||||
|
|
||||||
|
# protocols
|
||||||
|
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}")
|
||||||
|
|
||||||
|
function(protocol protoPath protoName external)
|
||||||
|
if (external)
|
||||||
|
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()
|
||||||
|
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()
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
make_directory(${CMAKE_SOURCE_DIR}/protocols) # we don't ship any custom ones so the dir won't be there
|
||||||
|
protocol("staging/ext-idle-notify/ext-idle-notify-v1.xml" "ext-idle-notify-v1" false)
|
||||||
|
|
||||||
|
# Installation
|
||||||
|
install(TARGETS hypridle)
|
76
src/config/ConfigManager.cpp
Normal file
76
src/config/ConfigManager.cpp
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
#include "ConfigManager.hpp"
|
||||||
|
#include <filesystem>
|
||||||
|
#include "../helpers/VarList.hpp"
|
||||||
|
|
||||||
|
static std::string getConfigDir() {
|
||||||
|
static const char* xdgConfigHome = getenv("XDG_CONFIG_HOME");
|
||||||
|
|
||||||
|
if (xdgConfigHome && std::filesystem::path(xdgConfigHome).is_absolute())
|
||||||
|
return xdgConfigHome;
|
||||||
|
|
||||||
|
return getenv("HOME") + std::string("/.config");
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string getMainConfigPath() {
|
||||||
|
return getConfigDir() + "/hypr/hypridle.conf";
|
||||||
|
}
|
||||||
|
|
||||||
|
CConfigManager::CConfigManager() : m_config(getMainConfigPath().c_str(), Hyprlang::SConfigOptions{.throwAllErrors = true, .allowMissingConfig = false}) {
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CConfigManager::init() {
|
||||||
|
m_config.addSpecialCategory("listener", Hyprlang::SSpecialCategoryOptions{.key = "timeout"});
|
||||||
|
m_config.addSpecialConfigValue("listener", "on-timeout", Hyprlang::STRING{""});
|
||||||
|
m_config.addSpecialConfigValue("listener", "on-resume", Hyprlang::STRING{""});
|
||||||
|
|
||||||
|
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;
|
||||||
|
uint64_t timeout = 0;
|
||||||
|
try {
|
||||||
|
timeout = std::stoull(std::any_cast<Hyprlang::STRING>(m_config.getSpecialConfigValue("listener", "timeout", k.c_str())));
|
||||||
|
} catch (std::exception& e) {
|
||||||
|
result.setError(
|
||||||
|
(std::string{"Faulty rule: cannot parse timeout "} + std::any_cast<Hyprlang::STRING>(m_config.getSpecialConfigValue("listener", "timeout", k.c_str()))).c_str());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
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()));
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
31
src/config/ConfigManager.hpp
Normal file
31
src/config/ConfigManager.hpp
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../helpers/Log.hpp"
|
||||||
|
|
||||||
|
#include <hyprlang.hpp>
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
class CConfigManager {
|
||||||
|
public:
|
||||||
|
CConfigManager();
|
||||||
|
void init();
|
||||||
|
|
||||||
|
struct STimeoutRule {
|
||||||
|
uint64_t timeout = 0;
|
||||||
|
std::string onTimeout = "";
|
||||||
|
std::string onResume = "";
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<STimeoutRule> getRules();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Hyprlang::CConfig m_config;
|
||||||
|
|
||||||
|
std::vector<STimeoutRule> m_vRules;
|
||||||
|
|
||||||
|
Hyprlang::CParseResult postParse();
|
||||||
|
};
|
||||||
|
|
||||||
|
inline std::unique_ptr<CConfigManager> g_pConfigManager;
|
167
src/core/Hypridle.cpp
Normal file
167
src/core/Hypridle.cpp
Normal file
|
@ -0,0 +1,167 @@
|
||||||
|
#include "Hypridle.hpp"
|
||||||
|
#include "../helpers/Log.hpp"
|
||||||
|
#include "../config/ConfigManager.hpp"
|
||||||
|
#include "signal.h"
|
||||||
|
#include <sys/wait.h>
|
||||||
|
|
||||||
|
CHypridle::CHypridle() {
|
||||||
|
m_sWaylandState.display = wl_display_connect(nullptr);
|
||||||
|
if (!m_sWaylandState.display) {
|
||||||
|
Debug::log(CRIT, "Couldn't connect to a wayland compositor");
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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() {
|
||||||
|
m_sWaylandState.registry = wl_display_get_registry(m_sWaylandState.display);
|
||||||
|
|
||||||
|
wl_registry_add_listener(m_sWaylandState.registry, ®istryListener, nullptr);
|
||||||
|
|
||||||
|
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?");
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto RULES = g_pConfigManager->getRules();
|
||||||
|
m_sWaylandIdleState.listeners.resize(RULES.size());
|
||||||
|
|
||||||
|
for (size_t i = 0; i < RULES.size(); ++i) {
|
||||||
|
auto& l = m_sWaylandIdleState.listeners[i];
|
||||||
|
const auto& r = RULES[i];
|
||||||
|
l.notification = ext_idle_notifier_v1_get_idle_notification(m_sWaylandIdleState.notifier, r.timeout * 1000 /* ms */, m_sWaylandState.seat);
|
||||||
|
l.onRestore = r.onResume;
|
||||||
|
l.onTimeout = r.onTimeout;
|
||||||
|
|
||||||
|
ext_idle_notification_v1_add_listener(l.notification, &idleListener, &l);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (wl_display_dispatch(m_sWaylandState.display) != -1) {
|
||||||
|
;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
Debug::log(LOG, "Executing {}", args);
|
||||||
|
|
||||||
|
int socket[2];
|
||||||
|
if (pipe(socket) != 0) {
|
||||||
|
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 child to init
|
||||||
|
waitpid(child, NULL, 0);
|
||||||
|
if (child < 0) {
|
||||||
|
Debug::log(LOG, "Failed to create the second fork");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Debug::log(LOG, "Process Created with pid {}", grandchild);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CHypridle::onIdled(SIdleListener* pListener) {
|
||||||
|
Debug::log(LOG, "Idled: rule {:x}", (uintptr_t)pListener);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
if (pListener->onRestore.empty()) {
|
||||||
|
Debug::log(LOG, "Ignoring, onRestore is empty.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Debug::log(LOG, "Running {}", pListener->onRestore);
|
||||||
|
spawn(pListener->onRestore);
|
||||||
|
}
|
41
src/core/Hypridle.hpp
Normal file
41
src/core/Hypridle.hpp
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
#include <wayland-client.h>
|
||||||
|
|
||||||
|
#include "ext-idle-notify-v1-protocol.h"
|
||||||
|
|
||||||
|
class CHypridle {
|
||||||
|
public:
|
||||||
|
CHypridle();
|
||||||
|
|
||||||
|
struct SIdleListener {
|
||||||
|
ext_idle_notification_v1* notification = nullptr;
|
||||||
|
std::string onTimeout = "";
|
||||||
|
std::string onRestore = "";
|
||||||
|
};
|
||||||
|
|
||||||
|
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*);
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct {
|
||||||
|
wl_display* display = nullptr;
|
||||||
|
wl_registry* registry = nullptr;
|
||||||
|
wl_seat* seat = nullptr;
|
||||||
|
} m_sWaylandState;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
ext_idle_notifier_v1* notifier = nullptr;
|
||||||
|
|
||||||
|
std::vector<SIdleListener> listeners;
|
||||||
|
} m_sWaylandIdleState;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline std::unique_ptr<CHypridle> g_pHypridle;
|
54
src/helpers/Log.hpp
Normal file
54
src/helpers/Log.hpp
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
#pragma once
|
||||||
|
#include <format>
|
||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
enum eLogLevel {
|
||||||
|
TRACE = 0,
|
||||||
|
INFO,
|
||||||
|
LOG,
|
||||||
|
WARN,
|
||||||
|
ERR,
|
||||||
|
CRIT
|
||||||
|
};
|
||||||
|
|
||||||
|
#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;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "] ";
|
||||||
|
|
||||||
|
std::cout << std::vformat(fmt, std::make_format_args(args...)) << "\n";
|
||||||
|
}
|
||||||
|
};
|
56
src/helpers/VarList.cpp
Normal file
56
src/helpers/VarList.cpp
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
#include "VarList.hpp"
|
||||||
|
#include <ranges>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <string_view>
|
||||||
|
|
||||||
|
static std::string removeBeginEndSpacesTabs(std::string str) {
|
||||||
|
if (str.empty())
|
||||||
|
return str;
|
||||||
|
|
||||||
|
int countBefore = 0;
|
||||||
|
while (str[countBefore] == ' ' || str[countBefore] == '\t') {
|
||||||
|
countBefore++;
|
||||||
|
}
|
||||||
|
|
||||||
|
int countAfter = 0;
|
||||||
|
while ((int)str.length() - countAfter - 1 >= 0 && (str[str.length() - countAfter - 1] == ' ' || str[str.length() - 1 - countAfter] == '\t')) {
|
||||||
|
countAfter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
str = str.substr(countBefore, str.length() - countBefore - countAfter);
|
||||||
|
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
CVarList::CVarList(const std::string& in, const size_t lastArgNo, const char delim, const bool removeEmpty) {
|
||||||
|
if (in.empty())
|
||||||
|
m_vArgs.emplace_back("");
|
||||||
|
|
||||||
|
std::string args{in};
|
||||||
|
size_t idx = 0;
|
||||||
|
size_t pos = 0;
|
||||||
|
std::ranges::replace_if(
|
||||||
|
args, [&](const char& c) { return delim == 's' ? std::isspace(c) : c == delim; }, 0);
|
||||||
|
|
||||||
|
for (const auto& s : args | std::views::split(0)) {
|
||||||
|
if (removeEmpty && s.empty())
|
||||||
|
continue;
|
||||||
|
if (++idx == lastArgNo) {
|
||||||
|
m_vArgs.emplace_back(removeBeginEndSpacesTabs(in.substr(pos)));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
pos += s.size() + 1;
|
||||||
|
m_vArgs.emplace_back(removeBeginEndSpacesTabs(std::string_view{s}.data()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string CVarList::join(const std::string& joiner, size_t from, size_t to) const {
|
||||||
|
size_t last = to == 0 ? size() : to;
|
||||||
|
|
||||||
|
std::string rolling;
|
||||||
|
for (size_t i = from; i < last; ++i) {
|
||||||
|
rolling += m_vArgs[i] + (i + 1 < last ? joiner : "");
|
||||||
|
}
|
||||||
|
|
||||||
|
return rolling;
|
||||||
|
}
|
63
src/helpers/VarList.hpp
Normal file
63
src/helpers/VarList.hpp
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
#pragma once
|
||||||
|
#include <functional>
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
class CVarList {
|
||||||
|
public:
|
||||||
|
/** Split string into arg list
|
||||||
|
@param lastArgNo stop splitting after argv reaches maximum size, last arg will contain rest of unsplit args
|
||||||
|
@param delim if delimiter is 's', use std::isspace
|
||||||
|
@param removeEmpty remove empty args from argv
|
||||||
|
*/
|
||||||
|
CVarList(const std::string& in, const size_t maxSize = 0, const char delim = ',', const bool removeEmpty = false);
|
||||||
|
|
||||||
|
~CVarList() = default;
|
||||||
|
|
||||||
|
size_t size() const {
|
||||||
|
return m_vArgs.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string join(const std::string& joiner, size_t from = 0, size_t to = 0) const;
|
||||||
|
|
||||||
|
void map(std::function<void(std::string&)> func) {
|
||||||
|
for (auto& s : m_vArgs)
|
||||||
|
func(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
void append(const std::string arg) {
|
||||||
|
m_vArgs.emplace_back(arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string operator[](const size_t& idx) const {
|
||||||
|
if (idx >= m_vArgs.size())
|
||||||
|
return "";
|
||||||
|
return m_vArgs[idx];
|
||||||
|
}
|
||||||
|
|
||||||
|
// for range-based loops
|
||||||
|
std::vector<std::string>::iterator begin() {
|
||||||
|
return m_vArgs.begin();
|
||||||
|
}
|
||||||
|
std::vector<std::string>::const_iterator begin() const {
|
||||||
|
return m_vArgs.begin();
|
||||||
|
}
|
||||||
|
std::vector<std::string>::iterator end() {
|
||||||
|
return m_vArgs.end();
|
||||||
|
}
|
||||||
|
std::vector<std::string>::const_iterator end() const {
|
||||||
|
return m_vArgs.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool contains(const std::string& el) {
|
||||||
|
for (auto& a : m_vArgs) {
|
||||||
|
if (a == el)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<std::string> m_vArgs;
|
||||||
|
};
|
14
src/main.cpp
Normal file
14
src/main.cpp
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
|
||||||
|
#include "config/ConfigManager.hpp"
|
||||||
|
#include "core/Hypridle.hpp"
|
||||||
|
|
||||||
|
int main(int argc, char** argv, char** envp) {
|
||||||
|
|
||||||
|
g_pConfigManager = std::make_unique<CConfigManager>();
|
||||||
|
g_pConfigManager->init();
|
||||||
|
|
||||||
|
g_pHypridle = std::make_unique<CHypridle>();
|
||||||
|
g_pHypridle->run();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in a new issue