aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Compositor.cpp14
-rw-r--r--src/config/ConfigDescriptions.hpp6
-rw-r--r--src/config/ConfigManager.cpp3
-rw-r--r--src/helpers/MiscFunctions.cpp32
-rw-r--r--src/helpers/MiscFunctions.hpp1
-rw-r--r--src/managers/VersionKeeperManager.cpp153
-rw-r--r--src/managers/VersionKeeperManager.hpp17
7 files changed, 224 insertions, 2 deletions
diff --git a/src/Compositor.cpp b/src/Compositor.cpp
index 1261d003..74a2c8d1 100644
--- a/src/Compositor.cpp
+++ b/src/Compositor.cpp
@@ -6,6 +6,7 @@
#include "managers/TokenManager.hpp"
#include "managers/PointerManager.hpp"
#include "managers/SeatManager.hpp"
+#include "managers/VersionKeeperManager.hpp"
#include "managers/eventLoop/EventLoopManager.hpp"
#include <aquamarine/output/Output.hpp>
#include <bit>
@@ -645,6 +646,9 @@ void CCompositor::initManagers(eManagersInitStage stage) {
Debug::log(LOG, "Creating the CursorManager!");
g_pCursorManager = std::make_unique<CCursorManager>();
+ Debug::log(LOG, "Creating the VersionKeeper!");
+ g_pVersionKeeperMgr = std::make_unique<CVersionKeeperManager>();
+
Debug::log(LOG, "Starting XWayland");
g_pXWayland = std::make_unique<CXWayland>(g_pCompositor->m_bEnableXwayland);
} break;
@@ -2610,7 +2614,8 @@ WORKSPACEID CCompositor::getNewSpecialID() {
}
void CCompositor::performUserChecks() {
- static auto PNOCHECKXDG = CConfigValue<Hyprlang::INT>("misc:disable_xdg_env_checks");
+ static auto PNOCHECKXDG = CConfigValue<Hyprlang::INT>("misc:disable_xdg_env_checks");
+ static auto PNOCHECKQTUTILS = CConfigValue<Hyprlang::INT>("misc:disable_hyprland_qtutils_check");
if (!*PNOCHECKXDG) {
const auto CURRENT_DESKTOP_ENV = getenv("XDG_CURRENT_DESKTOP");
@@ -2622,6 +2627,13 @@ void CCompositor::performUserChecks() {
}
}
+ if (!*PNOCHECKQTUTILS) {
+ if (!executableExistsInPath("hyprland-dialog")) {
+ g_pHyprNotificationOverlay->addNotification(
+ "Your system does not have hyprland-qtutils installed. This is a runtime dependency for some dialogs. Consider installing it.", CHyprColor{}, 15000, ICON_WARNING);
+ }
+ }
+
if (g_pHyprOpenGL->failedAssetsNo > 0) {
g_pHyprNotificationOverlay->addNotification(std::format("Hyprland failed to load {} essential asset{}, blame your distro's packager for doing a bad job at packaging!",
g_pHyprOpenGL->failedAssetsNo, g_pHyprOpenGL->failedAssetsNo > 1 ? "s" : ""),
diff --git a/src/config/ConfigDescriptions.hpp b/src/config/ConfigDescriptions.hpp
index b95eeab1..a1d4858c 100644
--- a/src/config/ConfigDescriptions.hpp
+++ b/src/config/ConfigDescriptions.hpp
@@ -1134,6 +1134,12 @@ inline static const std::vector<SConfigOptionDescription> CONFIG_OPTIONS = {
.data = SConfigOptionDescription::SBoolData{false},
},
SConfigOptionDescription{
+ .value = "misc:disable_hyprland_qtutils_check",
+ .description = "disable the warning if hyprland-qtutils is missing",
+ .type = CONFIG_OPTION_BOOL,
+ .data = SConfigOptionDescription::SBoolData{false},
+ },
+ SConfigOptionDescription{
.value = "misc:lockdead_screen_delay",
.description = "the delay in ms after the lockdead screen appears if the lock screen did not appear after a lock event occurred.",
.type = CONFIG_OPTION_INT,
diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp
index 820844eb..50fbe403 100644
--- a/src/config/ConfigManager.cpp
+++ b/src/config/ConfigManager.cpp
@@ -383,6 +383,7 @@ CConfigManager::CConfigManager() {
m_pConfig->addConfigValue("misc:middle_click_paste", Hyprlang::INT{1});
m_pConfig->addConfigValue("misc:render_unfocused_fps", Hyprlang::INT{15});
m_pConfig->addConfigValue("misc:disable_xdg_env_checks", Hyprlang::INT{0});
+ m_pConfig->addConfigValue("misc:disable_hyprland_qtutils_check", Hyprlang::INT{0});
m_pConfig->addConfigValue("misc:lockdead_screen_delay", Hyprlang::INT{1000});
m_pConfig->addConfigValue("group:insert_after_current", Hyprlang::INT{1});
@@ -606,6 +607,8 @@ CConfigManager::CConfigManager() {
m_pConfig->addConfigValue("render:direct_scanout", Hyprlang::INT{0});
m_pConfig->addConfigValue("render:expand_undersized_textures", Hyprlang::INT{1});
+ m_pConfig->addConfigValue("ecosystem:no_update_news", Hyprlang::INT{0});
+
// devices
m_pConfig->addSpecialCategory("device", {"name"});
m_pConfig->addSpecialConfigValue("device", "sensitivity", {0.F});
diff --git a/src/helpers/MiscFunctions.cpp b/src/helpers/MiscFunctions.cpp
index dc181d4f..2da90eb7 100644
--- a/src/helpers/MiscFunctions.cpp
+++ b/src/helpers/MiscFunctions.cpp
@@ -930,4 +930,34 @@ float stringToPercentage(const std::string& VALUE, const float REL) {
return (std::stof(VALUE.substr(0, VALUE.length() - 1)) * REL) / 100.f;
else
return std::stof(VALUE);
-};
+}
+
+bool executableExistsInPath(const std::string& exe) {
+ if (!getenv("PATH"))
+ return false;
+
+ static CVarList paths(getenv("PATH"), 0, ':', true);
+
+ for (auto& p : paths) {
+ std::string path = p + std::string{"/"} + exe;
+ std::error_code ec;
+ if (!std::filesystem::exists(path, ec) || ec)
+ continue;
+
+ if (!std::filesystem::is_regular_file(path, ec) || ec)
+ continue;
+
+ auto stat = std::filesystem::status(path, ec);
+ if (ec)
+ continue;
+
+ auto perms = stat.permissions();
+
+ if (std::filesystem::perms::none == (perms & std::filesystem::perms::others_exec))
+ return false;
+
+ return true;
+ }
+
+ return false;
+}
diff --git a/src/helpers/MiscFunctions.hpp b/src/helpers/MiscFunctions.hpp
index bb686df4..018efbed 100644
--- a/src/helpers/MiscFunctions.hpp
+++ b/src/helpers/MiscFunctions.hpp
@@ -42,6 +42,7 @@ bool envEnabled(const std::string& env);
int allocateSHMFile(size_t len);
bool allocateSHMFilePair(size_t size, int* rw_fd_ptr, int* ro_fd_ptr);
float stringToPercentage(const std::string& VALUE, const float REL);
+bool executableExistsInPath(const std::string& exe);
template <typename... Args>
[[deprecated("use std::format instead")]] std::string getFormat(std::format_string<Args...> fmt, Args&&... args) {
diff --git a/src/managers/VersionKeeperManager.cpp b/src/managers/VersionKeeperManager.cpp
new file mode 100644
index 00000000..89f7823d
--- /dev/null
+++ b/src/managers/VersionKeeperManager.cpp
@@ -0,0 +1,153 @@
+#include "VersionKeeperManager.hpp"
+#include "../debug/Log.hpp"
+#include "../macros.hpp"
+#include "../version.h"
+#include "../helpers/MiscFunctions.hpp"
+#include "../helpers/varlist/VarList.hpp"
+#include "eventLoop/EventLoopManager.hpp"
+#include "../config/ConfigValue.hpp"
+
+#include <filesystem>
+#include <fstream>
+#include <hyprutils/string/String.hpp>
+#include <hyprutils/os/Process.hpp>
+
+using namespace Hyprutils::String;
+using namespace Hyprutils::OS;
+
+constexpr const char* VERSION_FILE_NAME = "lastVersion";
+
+CVersionKeeperManager::CVersionKeeperManager() {
+ static auto PNONOTIFY = CConfigValue<Hyprlang::INT>("ecosystem:no_update_news");
+
+ const auto DATAROOT = getDataHome();
+
+ if (!DATAROOT)
+ return;
+
+ const auto LASTVER = getDataLastVersion(*DATAROOT);
+
+ if (!LASTVER)
+ return;
+
+ if (!isVersionOlderThanRunning(*LASTVER)) {
+ Debug::log(LOG, "CVersionKeeperManager: Read version {} matches or is older than running.", *LASTVER);
+ return;
+ }
+
+ writeVersionToVersionFile(*DATAROOT);
+
+ if (*PNONOTIFY) {
+ Debug::log(LOG, "CVersionKeeperManager: updated, but update news is disabled in the config :(");
+ return;
+ }
+
+ if (!executableExistsInPath("hyprland-update-screen")) {
+ Debug::log(ERR, "CVersionKeeperManager: hyprland-update-screen doesn't seem to exist, skipping notif about update...");
+ return;
+ }
+
+ g_pEventLoopManager->doLater([]() {
+ CProcess proc("hyprland-update-screen", {"--new-version", HYPRLAND_VERSION});
+ proc.runAsync();
+ });
+}
+
+std::optional<std::string> CVersionKeeperManager::getDataHome() {
+ const auto DATA_HOME = getenv("XDG_DATA_HOME");
+
+ std::string dataRoot;
+
+ if (!DATA_HOME) {
+ const auto HOME = getenv("HOME");
+
+ if (!HOME) {
+ Debug::log(ERR, "CVersionKeeperManager: can't get data home: no $HOME or $XDG_DATA_HOME");
+ return std::nullopt;
+ }
+
+ dataRoot = HOME + std::string{"/.local/share/"};
+ } else
+ dataRoot = DATA_HOME + std::string{"/"};
+
+ std::error_code ec;
+ if (!std::filesystem::exists(dataRoot, ec) || ec) {
+ Debug::log(ERR, "CVersionKeeperManager: can't get data home: inaccessible / missing");
+ return std::nullopt;
+ }
+
+ dataRoot += "hyprland/";
+
+ if (!std::filesystem::exists(dataRoot, ec) || ec) {
+ Debug::log(LOG, "CVersionKeeperManager: no hyprland data home, creating.");
+ std::filesystem::create_directory(dataRoot, ec);
+ if (ec) {
+ Debug::log(ERR, "CVersionKeeperManager: can't create new data home for hyprland");
+ return std::nullopt;
+ }
+ std::filesystem::permissions(dataRoot, std::filesystem::perms::owner_read | std::filesystem::perms::owner_write | std::filesystem::perms::owner_exec, ec);
+ if (ec)
+ Debug::log(WARN, "CVersionKeeperManager: couldn't set perms on hyprland data store. Proceeding anyways.");
+ }
+
+ if (!std::filesystem::exists(dataRoot, ec) || ec) {
+ Debug::log(ERR, "CVersionKeeperManager: no hyprland data home, failed to create.");
+ return std::nullopt;
+ }
+
+ return dataRoot;
+}
+
+std::optional<std::string> CVersionKeeperManager::getDataLastVersion(const std::string& dataRoot) {
+ std::error_code ec;
+ std::string lastVerFile = dataRoot + "/" + VERSION_FILE_NAME;
+
+ if (!std::filesystem::exists(lastVerFile, ec) || ec) {
+ Debug::log(LOG, "CVersionKeeperManager: no hyprland last version file, creating.");
+ writeVersionToVersionFile(dataRoot);
+
+ return HYPRLAND_VERSION;
+ }
+
+ std::ifstream file(lastVerFile);
+ if (!file.good()) {
+ Debug::log(ERR, "CVersionKeeperManager: couldn't open an ifstream for reading the version file.");
+ return std::nullopt;
+ }
+
+ return trim(std::string((std::istreambuf_iterator<char>(file)), (std::istreambuf_iterator<char>())));
+}
+
+void CVersionKeeperManager::writeVersionToVersionFile(const std::string& dataRoot) {
+ std::string lastVerFile = dataRoot + "/" + VERSION_FILE_NAME;
+ std::ofstream of(lastVerFile, std::ios::trunc);
+ if (!of.good()) {
+ Debug::log(ERR, "CVersionKeeperManager: couldn't open an ofstream for writing the version file.");
+ return;
+ }
+
+ of << HYPRLAND_VERSION;
+ of.close();
+}
+
+bool CVersionKeeperManager::isVersionOlderThanRunning(const std::string& ver) {
+ const CVarList verStrings(ver, 0, '.', true);
+
+ const int V1 = configStringToInt(verStrings[0]).value_or(0);
+ const int V2 = configStringToInt(verStrings[1]).value_or(0);
+ const int V3 = configStringToInt(verStrings[2]).value_or(0);
+
+ static const CVarList runningStrings(HYPRLAND_VERSION, 0, '.', true);
+
+ static const int R1 = configStringToInt(runningStrings[0]).value_or(0);
+ static const int R2 = configStringToInt(runningStrings[1]).value_or(0);
+ static const int R3 = configStringToInt(runningStrings[2]).value_or(0);
+
+ if (R1 > V1)
+ return true;
+ if (R2 > V2)
+ return true;
+ if (R3 > V3)
+ return true;
+ return false;
+}
diff --git a/src/managers/VersionKeeperManager.hpp b/src/managers/VersionKeeperManager.hpp
new file mode 100644
index 00000000..f0dc05ce
--- /dev/null
+++ b/src/managers/VersionKeeperManager.hpp
@@ -0,0 +1,17 @@
+#pragma once
+
+#include <memory>
+#include <optional>
+
+class CVersionKeeperManager {
+ public:
+ CVersionKeeperManager();
+
+ private:
+ std::optional<std::string> getDataHome();
+ std::optional<std::string> getDataLastVersion(const std::string& dataRoot);
+ void writeVersionToVersionFile(const std::string& dataRoot);
+ bool isVersionOlderThanRunning(const std::string& ver);
+};
+
+inline std::unique_ptr<CVersionKeeperManager> g_pVersionKeeperMgr; \ No newline at end of file